__  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

[email protected]: ~ $
#!/usr/bin/env python3

# Implements a target service according to the Web Service Discovery
# specification.
#
# The purpose is to enable non-Windows devices to be found by the 'Network
# (Neighborhood)' from Windows machines.
#
# see http://specs.xmlsoap.org/ws/2005/04/discovery/ws-discovery.pdf and
# related documents for details (look at README for more references)
#
# (c) Steffen Christgau, 2017-2024

import sys
import signal
import socket
import asyncio
import struct
import argparse
import uuid
import time
import random
import logging
import platform
import ctypes.util
import collections
import xml.etree.ElementTree as ElementTree
import http
import http.server
import urllib.request
import urllib.parse
import os
import pwd
import grp
import datetime

from typing import Any, Callable, ClassVar, Deque, Dict, List, Optional, Set, Union, Tuple, TYPE_CHECKING

# try to load more secure XML module first, fallback to default if not present
try:
    if not TYPE_CHECKING:
        from defusedxml.ElementTree import fromstring as ETfromString
except ModuleNotFoundError:
    from xml.etree.ElementTree import fromstring as ETfromString


WSDD_VERSION: str = '0.8'


args: argparse.Namespace
logger: logging.Logger


class NetworkInterface:

    _name: str
    _index: int
    _scope: int

    def __init__(self, name: str, scope: int, index: int) -> None:
        self._name = name
        self._scope = scope
        if index is not None:
            self._index = index
        else:
            self._index = socket.if_nametoindex(self._name)

    @property
    def name(self) -> str:
        return self._name

    @property
    def scope(self) -> int:
        return self._scope

    @property
    def index(self) -> int:
        return self._index

    def __str__(self) -> str:
        return self._name

    def __eq__(self, other) -> bool:
        return self._name == other.name


class NetworkAddress:

    _family: int
    _raw_address: bytes
    _address_str: str
    _interface: NetworkInterface

    def __init__(self, family: int, raw: Union[bytes, str], interface: NetworkInterface) -> None:
        self._family = family
        self._raw_address = raw if isinstance(raw, bytes) else socket.inet_pton(family, raw.partition('%')[0])
        self._interface = interface

        self._address_str = socket.inet_ntop(self._family, self._raw_address)

    @property
    def address_str(self):
        return self._address_str

    @property
    def family(self):
        return self._family

    @property
    def interface(self):
        return self._interface

    @property
    def is_multicastable(self):
        # Nah, this check is not optimal but there are no local flags for
        # addresses, but it should be safe for IPv4 anyways
        # (https://tools.ietf.org/html/rfc5735#page-3)
        return ((self._family == socket.AF_INET) and (self._raw_address[0] == 127)
                or (self._family == socket.AF_INET6) and (self._raw_address[0:2] != b'\xfe\x80'))

    @property
    def raw(self):
        return self._raw_address

    @property
    def transport_str(self):
        """the string representation of the local address overridden in network setup (for IPv6)"""
        return self._address_str if self._family == socket.AF_INET else '[{}]'.format(self._address_str)

    def __str__(self) -> str:
        return '{}%{}'.format(self._address_str, self._interface.name)

    def __eq__(self, other) -> bool:
        return (self._family == other.family and self.raw == other.raw and self.interface == other.interface)


class UdpAddress(NetworkAddress):

    _transport_address: Tuple
    _port: int

    def __init__(self, family, transport_address: Tuple, interface: NetworkInterface) -> None:

        if not (family == socket.AF_INET or family == socket.AF_INET6):
            raise RuntimeError('Unsupport address address family: {}.'.format(family))

        self._transport_address = transport_address
        self._port = transport_address[1]

        super().__init__(family, transport_address[0], interface)

    @property
    def transport_address(self):
        return self._transport_address

    @property
    def port(self):
        return self._port

    def __eq__(self, other) -> bool:
        return self.transport_address == other.transport_address


class INetworkPacketHandler:

    def handle_packet(self, msg: str, udp_src_address: UdpAddress) -> None:
        pass


class MulticastHandler:
    """
    A class for handling multicast traffic on a given interface for a
    given address family. It provides multicast sender and receiver sockets
    """

    # base interface addressing information
    address: NetworkAddress

    # individual interface-bound sockets for:
    #  - receiving multicast traffic
    #  - sending multicast from a socket bound to WSD port
    #  - sending unicast messages from a random port
    recv_socket: socket.socket
    mc_send_socket: socket.socket
    uc_send_socket: socket.socket

    # addresses used for communication and data
    multicast_address: UdpAddress
    listen_address: Tuple
    aio_loop: asyncio.AbstractEventLoop

    # dictionary that holds INetworkPacketHandlers instances for sockets created above
    message_handlers: Dict[socket.socket, List[INetworkPacketHandler]]

    def __init__(self, address: NetworkAddress, aio_loop: asyncio.AbstractEventLoop) -> None:
        self.address = address

        self.recv_socket = socket.socket(self.address.family, socket.SOCK_DGRAM)
        self.recv_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.mc_send_socket = socket.socket(self.address.family, socket.SOCK_DGRAM)
        self.uc_send_socket = socket.socket(self.address.family, socket.SOCK_DGRAM)
        self.uc_send_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        self.message_handlers = {}
        self.aio_loop = aio_loop

        if self.address.family == socket.AF_INET:
            self.init_v4()
        elif self.address.family == socket.AF_INET6:
            self.init_v6()

        logger.info('joined multicast group {0} on {1}'.format(self.multicast_address.transport_str, self.address))
        logger.debug('transport address on {0} is {1}'.format(self.address.interface.name, self.address.transport_str))
        logger.debug('will listen for HTTP traffic on address {0}'.format(self.listen_address))

        # register calbacks for incoming data (also for mc)
        self.aio_loop.add_reader(self.recv_socket.fileno(), self.read_socket, self.recv_socket)
        self.aio_loop.add_reader(self.mc_send_socket.fileno(), self.read_socket, self.mc_send_socket)
        self.aio_loop.add_reader(self.uc_send_socket.fileno(), self.read_socket, self.uc_send_socket)

    def cleanup(self) -> None:
        self.aio_loop.remove_reader(self.recv_socket)
        self.aio_loop.remove_reader(self.mc_send_socket)
        self.aio_loop.remove_reader(self.uc_send_socket)

        self.recv_socket.close()
        self.mc_send_socket.close()
        self.uc_send_socket.close()

    def handles_address(self, address: NetworkAddress) -> bool:
        return self.address == address

    def init_v6(self) -> None:
        idx = self.address.interface.index
        raw_mc_addr = (WSD_MCAST_GRP_V6, WSD_UDP_PORT, 0x575C, idx)
        self.multicast_address = UdpAddress(self.address.family, raw_mc_addr, self.address.interface)

        # v6: member_request = { multicast_addr, intf_idx }
        mreq = (socket.inet_pton(self.address.family, WSD_MCAST_GRP_V6) + struct.pack('@I', idx))
        self.recv_socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
        self.recv_socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)

        # Could anyone ask the Linux folks for the rationale for this!?
        if platform.system() == 'Linux':
            try:
                # supported starting from Linux 4.20
                IPV6_MULTICAST_ALL = 29
                self.recv_socket.setsockopt(socket.IPPROTO_IPV6, IPV6_MULTICAST_ALL, 0)
            except OSError as e:
                logger.warning('cannot unset all_multicast: {}'.format(e))

        # bind to network interface, i.e. scope and handle OS differences,
        # see Stevens: Unix Network Programming, Section 21.6, last paragraph
        try:
            self.recv_socket.bind((WSD_MCAST_GRP_V6, WSD_UDP_PORT, 0, idx))
        except OSError:
            self.recv_socket.bind(('::', 0, 0, idx))

        # bind unicast socket to interface address and WSD's udp port
        self.uc_send_socket.bind((str(self.address), WSD_UDP_PORT, 0, idx))

        self.mc_send_socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_LOOP, 0)
        self.mc_send_socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, args.hoplimit)
        self.mc_send_socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, idx)

        self.listen_address = (self.address.address_str, WSD_HTTP_PORT, 0, idx)

    def init_v4(self) -> None:
        idx = self.address.interface.index
        raw_mc_addr = (WSD_MCAST_GRP_V4, WSD_UDP_PORT)
        self.multicast_address = UdpAddress(self.address.family, raw_mc_addr, self.address.interface)

        # v4: member_request (ip_mreqn) = { multicast_addr, intf_addr, idx }
        mreq = (socket.inet_pton(self.address.family, WSD_MCAST_GRP_V4) + self.address.raw + struct.pack('@I', idx))
        self.recv_socket.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

        if platform.system() == 'Linux':
            IP_MULTICAST_ALL = 49
            self.recv_socket.setsockopt(socket.IPPROTO_IP, IP_MULTICAST_ALL, 0)

        try:
            self.recv_socket.bind((WSD_MCAST_GRP_V4, WSD_UDP_PORT))
        except OSError:
            self.recv_socket.bind(('', WSD_UDP_PORT))

        # bind unicast socket to interface address and WSD's udp port
        self.uc_send_socket.bind((self.address.address_str, WSD_UDP_PORT))

        self.mc_send_socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, mreq)
        # OpenBSD requires the optlen to be sizeof(char) for LOOP and TTL options
        # (see also https://github.com/python/cpython/issues/67316)
        self.mc_send_socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, struct.pack('B', 0))
        self.mc_send_socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, struct.pack('B', args.hoplimit))

        self.listen_address = (self.address.address_str, WSD_HTTP_PORT)

    def add_handler(self, socket: socket.socket, handler: INetworkPacketHandler) -> None:
        # try:
        #    self.selector.register(socket, selectors.EVENT_READ, self)
        # except KeyError:
        #    # accept attempts of multiple registrations
        #    pass

        if socket in self.message_handlers:
            self.message_handlers[socket].append(handler)
        else:
            self.message_handlers[socket] = [handler]

    def remove_handler(self, socket: socket.socket, handler) -> None:
        if socket in self.message_handlers:
            if handler in self.message_handlers[socket]:
                self.message_handlers[socket].remove(handler)

    def read_socket(self, key: socket.socket) -> None:
        # TODO: refactor this
        s = None
        if key == self.uc_send_socket:
            s = self.uc_send_socket
        elif key == self.mc_send_socket:
            s = self.mc_send_socket
        elif key == self.recv_socket:
            s = self.recv_socket
        else:
            raise ValueError("Unknown socket passed as key.")

        msg, raw_address = s.recvfrom(WSD_MAX_LEN)
        address = UdpAddress(self.address.family, raw_address, self.address.interface)
        if s in self.message_handlers:
            for handler in self.message_handlers[s]:
                handler.handle_packet(msg.decode('utf-8'), address)

    def send(self, msg: bytes, addr: UdpAddress):
        # Request from a client must be answered from a socket that is bound
        # to the WSD port, i.e. the recv_socket. Messages to multicast
        # addresses are sent over the dedicated send socket.
        if addr == self.multicast_address:
            self.mc_send_socket.sendto(msg, addr.transport_address)
        else:
            self.uc_send_socket.sendto(msg, addr.transport_address)


# constants for WSD XML/SOAP parsing
WSA_URI: str = 'http://schemas.xmlsoap.org/ws/2004/08/addressing'
WSD_URI: str = 'http://schemas.xmlsoap.org/ws/2005/04/discovery'
WSDP_URI: str = 'http://schemas.xmlsoap.org/ws/2006/02/devprof'

namespaces: Dict[str, str] = {
    'soap': 'http://www.w3.org/2003/05/soap-envelope',
    'wsa': WSA_URI,
    'wsd': WSD_URI,
    'wsx': 'http://schemas.xmlsoap.org/ws/2004/09/mex',
    'wsdp': WSDP_URI,
    'pnpx': 'http://schemas.microsoft.com/windows/pnpx/2005/10',
    'pub': 'http://schemas.microsoft.com/windows/pub/2005/07'
}

WSD_MAX_KNOWN_MESSAGES: int = 10

WSD_PROBE: str = WSD_URI + '/Probe'
WSD_PROBE_MATCH: str = WSD_URI + '/ProbeMatches'
WSD_RESOLVE: str = WSD_URI + '/Resolve'
WSD_RESOLVE_MATCH: str = WSD_URI + '/ResolveMatches'
WSD_HELLO: str = WSD_URI + '/Hello'
WSD_BYE: str = WSD_URI + '/Bye'
WSD_GET: str = 'http://schemas.xmlsoap.org/ws/2004/09/transfer/Get'
WSD_GET_RESPONSE: str = 'http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse'

WSD_TYPE_DEVICE: str = 'wsdp:Device'
PUB_COMPUTER: str = 'pub:Computer'
WSD_TYPE_DEVICE_COMPUTER: str = '{0} {1}'.format(WSD_TYPE_DEVICE, PUB_COMPUTER)

WSD_MCAST_GRP_V4: str = '239.255.255.250'
WSD_MCAST_GRP_V6: str = 'ff02::c'  # link-local

WSA_ANON: str = WSA_URI + '/role/anonymous'
WSA_DISCOVERY: str = 'urn:schemas-xmlsoap-org:ws:2005:04:discovery'

MIME_TYPE_SOAP_XML: str = 'application/soap+xml'

# protocol assignments (WSD spec/Section 2.4)
WSD_UDP_PORT: int = 3702
WSD_HTTP_PORT: int = 5357
WSD_MAX_LEN: int = 32767

WSDD_LISTEN_PORT = 5359

# SOAP/UDP transmission constants
MULTICAST_UDP_REPEAT: int = 4
UNICAST_UDP_REPEAT: int = 2
UDP_MIN_DELAY: int = 50
UDP_MAX_DELAY: int = 250
UDP_UPPER_DELAY: int = 500

# servers must recond in 4 seconds after probe arrives
PROBE_TIMEOUT: int = 4
MAX_STARTUP_PROBE_DELAY: int = 3

# some globals
wsd_instance_id: int = int(time.time())

WSDMessage = Tuple[ElementTree.Element, str]
MessageTypeHandler = Callable[[ElementTree.Element, ElementTree.Element], Optional[WSDMessage]]


class WSDMessageHandler(INetworkPacketHandler):
    known_messages: Deque[str] = collections.deque([], WSD_MAX_KNOWN_MESSAGES)

    handlers: Dict[str, MessageTypeHandler]
    pending_tasks: List[asyncio.Task]

    def __init__(self) -> None:
        self.handlers = {}
        self.pending_tasks = []

    def cleanup(self):
        pass

    # shortcuts for building WSD responses
    def add_endpoint_reference(self, parent: ElementTree.Element, endpoint: Optional[str] = None) -> None:
        epr = ElementTree.SubElement(parent, 'wsa:EndpointReference')
        address = ElementTree.SubElement(epr, 'wsa:Address')
        if endpoint is None:
            address.text = args.uuid.urn
        else:
            address.text = endpoint

    def add_metadata_version(self, parent: ElementTree.Element) -> None:
        meta_data = ElementTree.SubElement(parent, 'wsd:MetadataVersion')
        meta_data.text = '1'

    def add_types(self, parent: ElementTree.Element) -> None:
        dev_type = ElementTree.SubElement(parent, 'wsd:Types')
        dev_type.text = WSD_TYPE_DEVICE_COMPUTER

    def add_xaddr(self, parent: ElementTree.Element, transport_addr: str) -> None:
        if transport_addr:
            item = ElementTree.SubElement(parent, 'wsd:XAddrs')
            item.text = 'http://{0}:{1}/{2}'.format(transport_addr, WSD_HTTP_PORT, args.uuid)

    def build_message(self, to_addr: str, action_str: str, request_header: Optional[ElementTree.Element],
                      response: ElementTree.Element) -> str:
        retval = self.xml_to_str(self.build_message_tree(to_addr, action_str, request_header, response)[0])

        logger.debug('constructed xml for WSD message: {0}'.format(retval))

        return retval

    def build_message_tree(self, to_addr: str, action_str: str, request_header: Optional[ElementTree.Element],
                           body: Optional[ElementTree.Element]) -> Tuple[ElementTree.Element, str]:
        """
        Build a WSD message with a given action string including SOAP header.

        The message can be constructed based on a response to another
        message (given by its header) and with a optional response that
        serves as the message's body
        """
        root = ElementTree.Element('soap:Envelope')
        header = ElementTree.SubElement(root, 'soap:Header')

        to = ElementTree.SubElement(header, 'wsa:To')
        to.text = to_addr

        action = ElementTree.SubElement(header, 'wsa:Action')
        action.text = action_str

        msg_id = ElementTree.SubElement(header, 'wsa:MessageID')
        msg_id.text = uuid.uuid1().urn

        if request_header is not None:
            req_msg_id = request_header.find('./wsa:MessageID', namespaces)
            if req_msg_id is not None:
                relates_to = ElementTree.SubElement(header, 'wsa:RelatesTo')
                relates_to.text = req_msg_id.text

        self.add_header_elements(header, action_str)

        body_root = ElementTree.SubElement(root, 'soap:Body')
        if body is not None:
            body_root.append(body)

        for prefix, uri in namespaces.items():
            root.attrib['xmlns:' + prefix] = uri

        return root, msg_id.text

    def add_header_elements(self, header: ElementTree.Element, extra: Any) -> None:
        pass

    def handle_message(self, msg: str, src: Optional[UdpAddress] = None) -> Optional[str]:
        """
        handle a WSD message
        """
        try:
            tree = ETfromString(msg)
        except ElementTree.ParseError:
            return None

        header = tree.find('./soap:Header', namespaces)
        if header is None:
            return None

        msg_id_tag = header.find('./wsa:MessageID', namespaces)
        if msg_id_tag is None:
            return None

        msg_id = str(msg_id_tag.text)

        # check for duplicates
        if self.is_duplicated_msg(msg_id):
            logger.debug('known message ({0}): dropping it'.format(msg_id))
            return None

        action_tag = header.find('./wsa:Action', namespaces)
        if action_tag is None:
            return None

        action: str = str(action_tag.text)
        _, _, action_method = action.rpartition('/')

        if src:
            logger.info('{}:{}({}) - - "{} {} UDP" - -'.format(
                src.transport_str, src.port, src.interface, action_method, msg_id))
        else:
            # http logging is already done by according server
            logger.debug('processing WSD {} message ({})'.format(action_method, msg_id))

        body = tree.find('./soap:Body', namespaces)
        if body is None:
            return None

        logger.debug('incoming message content is {0}'.format(msg))
        if action in self.handlers:
            handler = self.handlers[action]
            retval = handler(header, body)
            if retval is not None:
                response, response_type = retval
                return self.build_message(WSA_ANON, response_type, header, response)
        else:
            logger.debug('unhandled action {0}/{1}'.format(action, msg_id))

        return None

    def is_duplicated_msg(self, msg_id: str) -> bool:
        """
        Check for a duplicated message.

        Implements SOAP-over-UDP Appendix II Item 2
        """
        if msg_id in type(self).known_messages:
            return True

        type(self).known_messages.append(msg_id)

        return False

    def xml_to_str(self, xml: ElementTree.Element) -> str:
        retval = '<?xml version="1.0" encoding="utf-8"?>'
        retval = retval + ElementTree.tostring(xml, encoding='utf-8').decode('utf-8')

        return retval


class WSDUDPMessageHandler(WSDMessageHandler):
    """
    A message handler that handles traffic received via MutlicastHandler.
    """

    mch: MulticastHandler
    tearing_down: bool

    def __init__(self, mch: MulticastHandler) -> None:
        super().__init__()

        self.mch = mch
        self.tearing_down = False

    def teardown(self):
        self.tearing_down = True

    def send_datagram(self, msg: str, dst: UdpAddress) -> None:
        try:
            self.mch.send(msg.encode('utf-8'), dst)
        except Exception as e:
            logger.error('error while sending packet on {}: {}'.format(self.mch.address.interface, e))

    def enqueue_datagram(self, msg: str, address: UdpAddress, msg_type: Optional[str] = None) -> None:
        if msg_type:
            logger.info('scheduling {0} message via {1} to {2}'.format(msg_type, address.interface, address))

        schedule_task = self.mch.aio_loop.create_task(self.schedule_datagram(msg, address))
        # Add this task to the pending list during teardown to wait during shutdown
        if self.tearing_down:
            self.pending_tasks.append(schedule_task)

    async def schedule_datagram(self, msg: str, address: UdpAddress) -> None:
        """
        Schedule to send the given message to the given address.

        Implements SOAP over UDP, Appendix I.
        """

        self.send_datagram(msg, address)

        delta = 0
        msg_count = MULTICAST_UDP_REPEAT if address == self.mch.multicast_address else UNICAST_UDP_REPEAT
        delta = random.randint(UDP_MIN_DELAY, UDP_MAX_DELAY)
        for i in range(msg_count - 1):
            await asyncio.sleep(delta / 1000.0)
            self.send_datagram(msg, address)
            delta = min(delta * 2, UDP_UPPER_DELAY)


class WSDDiscoveredDevice:

    # a dict of discovered devices with their UUID as key
    instances: Dict[str, 'WSDDiscoveredDevice'] = {}

    addresses: Dict[str, Set[str]]
    props: Dict[str, str]
    display_name: str
    last_seen: float
    types: Set[str]

    def __init__(self, xml_str: str, xaddr: str, interface: NetworkInterface) -> None:
        self.last_seen = 0.0
        self.addresses = {}
        self.props = {}
        self.display_name = ''
        self.types = set()

        self.update(xml_str, xaddr, interface)

    def update(self, xml_str: str, xaddr: str, interface: NetworkInterface) -> None:
        try:
            tree = ETfromString(xml_str)
        except ElementTree.ParseError:
            return None
        mds_path = 'soap:Body/wsx:Metadata/wsx:MetadataSection'
        sections = tree.findall(mds_path, namespaces)
        for section in sections:
            dialect = section.attrib['Dialect']
            if dialect == WSDP_URI + '/ThisDevice':
                self.extract_wsdp_props(section, dialect)
            elif dialect == WSDP_URI + '/ThisModel':
                self.extract_wsdp_props(section, dialect)
            elif dialect == WSDP_URI + '/Relationship':
                host_xpath = 'wsdp:Relationship[@Type="{}/host"]/wsdp:Host'.format(WSDP_URI)
                host_sec = section.find(host_xpath, namespaces)
                if (host_sec):
                    self.extract_host_props(host_sec)
            else:
                logger.debug('unknown metadata dialect ({})'.format(dialect))

        url = urllib.parse.urlparse(xaddr)
        addr, _, _ = url.netloc.rpartition(':')
        report = True
        if interface.name not in self.addresses:
            self.addresses[interface.name] = set([addr])
        else:
            if addr not in self.addresses[interface.name]:
                self.addresses[interface.name].add(addr)
            else:
                report = False

        self.last_seen = time.time()
        if ('DisplayName' in self.props) and ('BelongsTo' in self.props) and (report):
            self.display_name = self.props['DisplayName']
            logger.info('discovered {} in {} on {}'.format(self.display_name, self.props['BelongsTo'], addr))
        elif ('FriendlyName' in self.props) and (report):
            self.display_name = self.props['FriendlyName']
            logger.info('discovered {} on {}'.format(self.display_name, addr))

        logger.debug(str(self.props))

    def extract_wsdp_props(self, root: ElementTree.Element, dialect: str) -> None:
        _, _, propsRoot = dialect.rpartition('/')
        # XPath support is limited, so filter by namespace on our own
        nodes = root.findall('./wsdp:{0}/*'.format(propsRoot), namespaces)
        ns_prefix = '{{{}}}'.format(WSDP_URI)
        prop_nodes = [n for n in nodes if n.tag.startswith(ns_prefix)]
        for node in prop_nodes:
            tag_name = node.tag[len(ns_prefix):]
            self.props[tag_name] = str(node.text)

    def extract_host_props(self, root: ElementTree.Element) -> None:
        self.types = set(root.findtext('wsdp:Types', '', namespaces).split(' '))
        if PUB_COMPUTER not in self.types:
            return

        comp = root.findtext(PUB_COMPUTER, '', namespaces)
        self.props['DisplayName'], _, self.props['BelongsTo'] = (
            comp.partition('/'))


class WSDClient(WSDUDPMessageHandler):

    instances: ClassVar[List['WSDClient']] = []
    probes: Dict[str, float]

    def __init__(self, mch: MulticastHandler) -> None:
        super().__init__(mch)

        WSDClient.instances.append(self)

        self.mch.add_handler(self.mch.mc_send_socket, self)
        self.mch.add_handler(self.mch.recv_socket, self)

        self.probes = {}

        self.handlers[WSD_HELLO] = self.handle_hello
        self.handlers[WSD_BYE] = self.handle_bye
        self.handlers[WSD_PROBE_MATCH] = self.handle_probe_match
        self.handlers[WSD_RESOLVE_MATCH] = self.handle_resolve_match

        # avoid packet storm when hosts come up by delaying initial probe
        time.sleep(random.randint(0, MAX_STARTUP_PROBE_DELAY))
        self.send_probe()

    def cleanup(self) -> None:
        super().cleanup()
        WSDClient.instances.remove(self)

        self.mch.remove_handler(self.mch.mc_send_socket, self)
        self.mch.remove_handler(self.mch.recv_socket, self)

    def send_probe(self) -> None:
        """WS-Discovery, Section 4.3, Probe message"""
        self.remove_outdated_probes()

        probe = ElementTree.Element('wsd:Probe')
        ElementTree.SubElement(probe, 'wsd:Types').text = WSD_TYPE_DEVICE

        xml, i = self.build_message_tree(WSA_DISCOVERY, WSD_PROBE, None, probe)
        self.enqueue_datagram(self.xml_to_str(xml), self.mch.multicast_address, msg_type='Probe')
        self.probes[i] = time.time()

    def teardown(self) -> None:
        super().teardown()
        self.remove_outdated_probes()

    def handle_packet(self, msg: str, src: Optional[UdpAddress] = None) -> None:
        self.handle_message(msg, src)

    def __extract_xaddr(self, xaddrs: str) -> Optional[str]:
        for addr in xaddrs.strip().split():
            if (self.mch.address.family == socket.AF_INET6) and ('//[fe80::' in addr):
                # use first link-local address for IPv6
                return addr
            elif self.mch.address.family == socket.AF_INET:
                # use first (and very likely the only) IPv4 address
                return addr

        return None

    def handle_hello(self, header: ElementTree.Element, body: ElementTree.Element) -> Optional[WSDMessage]:
        pm_path = 'wsd:Hello'
        endpoint, xaddrs = self.extract_endpoint_metadata(body, pm_path)
        if not xaddrs:
            logger.info('Hello without XAddrs, sending resolve')
            msg = self.build_resolve_message(str(endpoint))
            self.enqueue_datagram(msg, self.mch.multicast_address)
            return None

        xaddr = self.__extract_xaddr(xaddrs)
        if xaddr is None:
            return None

        logger.info('Hello from {} on {}'.format(endpoint, xaddr))
        self.perform_metadata_exchange(endpoint, xaddr)
        return None

    def handle_bye(self, header: ElementTree.Element, body: ElementTree.Element) -> Optional[WSDMessage]:
        bye_path = 'wsd:Bye'
        endpoint, _ = self.extract_endpoint_metadata(body, bye_path)
        device_uuid = str(uuid.UUID(endpoint))
        if device_uuid in WSDDiscoveredDevice.instances:
            del WSDDiscoveredDevice.instances[device_uuid]

        return None

    def handle_probe_match(self, header: ElementTree.Element, body: ElementTree.Element) -> Optional[WSDMessage]:
        # do not handle to probematches issued not sent by ourself
        rel_msg = header.findtext('wsa:RelatesTo', None, namespaces)
        if rel_msg not in self.probes:
            logger.debug("unknown probe {}".format(rel_msg))
            return None

        # if XAddrs are missing, issue resolve request
        pm_path = 'wsd:ProbeMatches/wsd:ProbeMatch'
        endpoint, xaddrs = self.extract_endpoint_metadata(body, pm_path)
        if not xaddrs:
            logger.debug('probe match without XAddrs, sending resolve')
            msg = self.build_resolve_message(str(endpoint))
            self.enqueue_datagram(msg, self.mch.multicast_address)
            return None

        xaddr = self.__extract_xaddr(xaddrs)
        if xaddr is None:
            return None

        logger.debug('probe match for {} on {}'.format(endpoint, xaddr))
        self.perform_metadata_exchange(endpoint, xaddr)

        return None

    def build_resolve_message(self, endpoint: str) -> str:
        resolve = ElementTree.Element('wsd:Resolve')
        self.add_endpoint_reference(resolve, endpoint)

        return self.build_message(WSA_DISCOVERY, WSD_RESOLVE, None, resolve)

    def handle_resolve_match(self, header: ElementTree.Element, body: ElementTree.Element) -> Optional[WSDMessage]:
        rm_path = 'wsd:ResolveMatches/wsd:ResolveMatch'
        endpoint, xaddrs = self.extract_endpoint_metadata(body, rm_path)
        if not endpoint or not xaddrs:
            logger.debug('resolve match without endpoint/xaddr')
            return None

        xaddr = self.__extract_xaddr(xaddrs)
        if xaddr is None:
            return None

        logger.debug('resolve match for {} on {}'.format(endpoint, xaddr))
        self.perform_metadata_exchange(endpoint, xaddr)

        return None

    def extract_endpoint_metadata(self, body: ElementTree.Element, prefix: str) -> Tuple[Optional[str], Optional[str]]:
        prefix = prefix + '/'
        addr_path = 'wsa:EndpointReference/wsa:Address'

        endpoint = body.findtext(prefix + addr_path, namespaces=namespaces)
        xaddrs = body.findtext(prefix + 'wsd:XAddrs', namespaces=namespaces)

        return endpoint, xaddrs

    def perform_metadata_exchange(self, endpoint, xaddr: str):
        if not (xaddr.startswith('http://') or xaddr.startswith('https://')):
            logger.debug('invalid XAddr: {}'.format(xaddr))
            return

        host = None
        url = xaddr
        if self.mch.address.family == socket.AF_INET6:
            host = '[{}]'.format(url.partition('[')[2].partition(']')[0])
            url = url.replace(']', '%{}]'.format(self.mch.address.interface))

        body = self.build_getmetadata_message(endpoint)
        request = urllib.request.Request(url, data=body.encode('utf-8'), method='POST')
        request.add_header('Content-Type', 'application/soap+xml')
        request.add_header('User-Agent', 'wsdd')
        if host is not None:
            request.add_header('Host', host)

        try:
            with urllib.request.urlopen(request, None, args.metadata_timeout) as stream:
                self.handle_metadata(stream.read(), endpoint, xaddr)
        except urllib.error.URLError as e:
            logger.warning('could not fetch metadata from: {} {}'.format(url, e))

    def build_getmetadata_message(self, endpoint) -> str:
        tree, _ = self.build_message_tree(endpoint, WSD_GET, None, None)
        return self.xml_to_str(tree)

    def handle_metadata(self, meta: str, endpoint: str, xaddr: str) -> None:
        device_uuid = str(uuid.UUID(endpoint))
        if device_uuid in WSDDiscoveredDevice.instances:
            WSDDiscoveredDevice.instances[device_uuid].update(meta, xaddr, self.mch.address.interface)
        else:
            WSDDiscoveredDevice.instances[device_uuid] = WSDDiscoveredDevice(meta, xaddr, self.mch.address.interface)

    def remove_outdated_probes(self) -> None:
        cut = time.time() - PROBE_TIMEOUT * 2
        self.probes = dict(filter(lambda x: x[1] > cut, self.probes.items()))

    def add_header_elements(self, header: ElementTree.Element, extra: Any) -> None:
        action_str = extra
        if action_str == WSD_GET:
            reply_to = ElementTree.SubElement(header, 'wsa:ReplyTo')
            addr = ElementTree.SubElement(reply_to, 'wsa:Address')
            addr.text = WSA_ANON

            wsa_from = ElementTree.SubElement(header, 'wsa:From')
            addr = ElementTree.SubElement(wsa_from, 'wsa:Address')
            addr.text = args.uuid.urn


class WSDHost(WSDUDPMessageHandler):
    """Class for handling WSD requests coming from UDP datagrams."""

    message_number: ClassVar[int] = 0
    instances: ClassVar[List['WSDHost']] = []

    def __init__(self, mch: MulticastHandler) -> None:
        super().__init__(mch)

        WSDHost.instances.append(self)

        self.mch.add_handler(self.mch.recv_socket, self)

        self.handlers[WSD_PROBE] = self.handle_probe
        self.handlers[WSD_RESOLVE] = self.handle_resolve

        self.send_hello()

    def cleanup(self) -> None:
        super().cleanup()
        WSDHost.instances.remove(self)

    def teardown(self) -> None:
        super().teardown()
        self.send_bye()

    def handle_packet(self, msg: str, src: UdpAddress) -> None:
        reply = self.handle_message(msg, src)
        if reply:
            self.enqueue_datagram(reply, src)

    def send_hello(self) -> None:
        """WS-Discovery, Section 4.1, Hello message"""
        hello = ElementTree.Element('wsd:Hello')
        self.add_endpoint_reference(hello)
        # THINK: Microsoft does not send the transport address here due to privacy reasons. Could make this optional.
        self.add_xaddr(hello, self.mch.address.transport_str)
        self.add_metadata_version(hello)

        msg = self.build_message(WSA_DISCOVERY, WSD_HELLO, None, hello)
        self.enqueue_datagram(msg, self.mch.multicast_address, msg_type='Hello')

    def send_bye(self) -> None:
        """WS-Discovery, Section 4.2, Bye message"""
        bye = ElementTree.Element('wsd:Bye')
        self.add_endpoint_reference(bye)

        msg = self.build_message(WSA_DISCOVERY, WSD_BYE, None, bye)
        self.enqueue_datagram(msg, self.mch.multicast_address, msg_type='Bye')

    def handle_probe(self, header: ElementTree.Element, body: ElementTree.Element) -> Optional[WSDMessage]:
        probe = body.find('./wsd:Probe', namespaces)
        if probe is None:
            return None

        scopes = probe.find('./wsd:Scopes', namespaces)

        if scopes:
            # THINK: send fault message (see p. 21 in WSD)
            logger.debug('scopes ({}) unsupported but probed'.format(scopes))
            return None

        types_elem = probe.find('./wsd:Types', namespaces)
        if types_elem is None:
            logger.debug('Probe message lacks wsd:Types element. Ignored.')
            return None

        types = types_elem.text
        if not types == WSD_TYPE_DEVICE:
            logger.debug('unknown discovery type ({}) for probe'.format(types))
            return None

        matches = ElementTree.Element('wsd:ProbeMatches')
        match = ElementTree.SubElement(matches, 'wsd:ProbeMatch')
        self.add_endpoint_reference(match)
        self.add_types(match)
        self.add_metadata_version(match)

        return matches, WSD_PROBE_MATCH

    def handle_resolve(self, header: ElementTree.Element, body: ElementTree.Element) -> Optional[WSDMessage]:
        resolve = body.find('./wsd:Resolve', namespaces)
        if resolve is None:
            return None

        addr = resolve.find('./wsa:EndpointReference/wsa:Address', namespaces)
        if addr is None:
            logger.debug('invalid resolve request: missing endpoint address')
            return None

        if not addr.text == args.uuid.urn:
            logger.debug('invalid resolve request: address ({}) does not match own one ({})'.format(
                addr.text, args.uuid.urn))
            return None

        matches = ElementTree.Element('wsd:ResolveMatches')
        match = ElementTree.SubElement(matches, 'wsd:ResolveMatch')
        self.add_endpoint_reference(match)
        self.add_types(match)
        self.add_xaddr(match, self.mch.address.transport_str)
        self.add_metadata_version(match)

        return matches, WSD_RESOLVE_MATCH

    def add_header_elements(self, header: ElementTree.Element, extra: Any):
        ElementTree.SubElement(header, 'wsd:AppSequence', {
            'InstanceId': str(wsd_instance_id),
            'SequenceId': uuid.uuid1().urn,
            'MessageNumber': str(type(self).message_number)})

        type(self).message_number += 1


class WSDHttpMessageHandler(WSDMessageHandler):

    def __init__(self) -> None:
        super().__init__()

        self.handlers[WSD_GET] = self.handle_get

    def handle_get(self, header: ElementTree.Element, body: ElementTree.Element) -> WSDMessage:
        # see https://msdn.microsoft.com/en-us/library/hh441784.aspx for an
        # example. Some of the properties below might be made configurable
        # in future releases.
        metadata = ElementTree.Element('wsx:Metadata')
        section = ElementTree.SubElement(metadata, 'wsx:MetadataSection', {'Dialect': WSDP_URI + '/ThisDevice'})
        device = ElementTree.SubElement(section, 'wsdp:ThisDevice')
        ElementTree.SubElement(device, 'wsdp:FriendlyName').text = ('WSD Device {0}'.format(args.hostname))
        ElementTree.SubElement(device, 'wsdp:FirmwareVersion').text = '1.0'
        ElementTree.SubElement(device, 'wsdp:SerialNumber').text = '1'

        section = ElementTree.SubElement(metadata, 'wsx:MetadataSection', {'Dialect': WSDP_URI + '/ThisModel'})
        model = ElementTree.SubElement(section, 'wsdp:ThisModel')
        ElementTree.SubElement(model, 'wsdp:Manufacturer').text = 'wsdd'
        ElementTree.SubElement(model, 'wsdp:ModelName').text = 'wsdd'
        ElementTree.SubElement(model, 'pnpx:DeviceCategory').text = 'Computers'

        section = ElementTree.SubElement(metadata, 'wsx:MetadataSection', {'Dialect': WSDP_URI + '/Relationship'})
        rel = ElementTree.SubElement(section, 'wsdp:Relationship', {'Type': WSDP_URI + '/host'})
        host = ElementTree.SubElement(rel, 'wsdp:Host')
        self.add_endpoint_reference(host)
        ElementTree.SubElement(host, 'wsdp:Types').text = PUB_COMPUTER
        ElementTree.SubElement(host, 'wsdp:ServiceId').text = args.uuid.urn

        fmt = '{0}/Domain:{1}' if args.domain else '{0}/Workgroup:{1}'
        value = args.domain if args.domain else args.workgroup.upper()
        if args.domain:
            dh = args.hostname if args.preserve_case else args.hostname.lower()
        else:
            dh = args.hostname if args.preserve_case else args.hostname.upper()

        ElementTree.SubElement(host, PUB_COMPUTER).text = fmt.format(dh, value)

        return metadata, WSD_GET_RESPONSE


class WSDHttpServer(http.server.HTTPServer):
    """ HTTP server both with IPv6 support and WSD handling """

    mch: MulticastHandler
    aio_loop: asyncio.AbstractEventLoop
    wsd_handler: WSDHttpMessageHandler
    registered: bool

    def __init__(self, mch: MulticastHandler, aio_loop: asyncio.AbstractEventLoop):
        # hacky way to convince HTTP/SocketServer of the address family
        type(self).address_family = mch.address.family

        self.mch = mch
        self.aio_loop = aio_loop
        self.wsd_handler = WSDHttpMessageHandler()
        self.registered = False

        # WSDHttpRequestHandler is a BaseHTTPRequestHandler. Passing to the parent constructor is therefore safe and
        # we can ignore the type error reported by mypy
        super().__init__(mch.listen_address, WSDHttpRequestHandler)  # type: ignore

    def server_bind(self) -> None:
        if self.mch.address.family == socket.AF_INET6:
            self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)

        super().server_bind()

    def server_activate(self) -> None:
        super().server_activate()
        self.aio_loop.add_reader(self.fileno(), self.handle_request)
        self.registered = True

    def server_close(self) -> None:
        if self.registered:
            self.aio_loop.remove_reader(self.fileno())
        super().server_close()


class WSDHttpRequestHandler(http.server.BaseHTTPRequestHandler):
    """Class for handling WSD requests coming over HTTP"""

    def log_message(self, fmt, *args) -> None:
        logger.info("{} - - ".format(self.address_string()) + fmt % args)

    def do_POST(self) -> None:
        if self.path != '/' + str(args.uuid):
            self.send_error(http.HTTPStatus.NOT_FOUND)

        ct = self.headers['Content-Type']
        if ct is None or not ct.startswith(MIME_TYPE_SOAP_XML):
            self.send_error(http.HTTPStatus.BAD_REQUEST, 'Invalid Content-Type')

        content_length = int(self.headers['Content-Length'])
        body = self.rfile.read(content_length)

        response = self.server.wsd_handler.handle_message(body)  # type: ignore
        if response:
            self.send_response(http.HTTPStatus.OK)
            self.send_header('Content-Type', MIME_TYPE_SOAP_XML)
            self.end_headers()
            self.wfile.write(response.encode('utf-8'))
        else:
            self.send_error(http.HTTPStatus.BAD_REQUEST)


class ApiServer:

    address_monitor: 'NetworkAddressMonitor'

    def __init__(self, aio_loop: asyncio.AbstractEventLoop, listen_address: bytes,
                 address_monitor: 'NetworkAddressMonitor') -> None:
        self.server = None
        self.address_monitor = address_monitor

        # defer server creation
        self.create_task = aio_loop.create_task(self.create_server(aio_loop, listen_address))

    async def create_server(self, aio_loop: asyncio.AbstractEventLoop, listen_address: Any) -> None:

        # It appears mypy is not able to check the argument to create_task and the return value of start_server
        # correctly. The docs say start_server returns a coroutine and the create_task takes a coro. And: It works.
        # Thus, we ignore type errors here.
        if isinstance(listen_address, int) or listen_address.isnumeric():
            self.server = await aio_loop.create_task(asyncio.start_server(  # type: ignore
                self.on_connect, host='localhost', port=int(listen_address), reuse_address=True,
                reuse_port=True))
        else:
            self.server = await aio_loop.create_task(asyncio.start_unix_server(  # type: ignore
                self.on_connect, path=listen_address))

    async def on_connect(self, read_stream: asyncio.StreamReader, write_stream: asyncio.StreamWriter) -> None:
        while True:
            try:
                line = await read_stream.readline()
                if line:
                    self.handle_command(str(line.strip(), 'utf-8'), write_stream)
                    if not write_stream.is_closing():
                        await write_stream.drain()
                else:
                    write_stream.close()
                    return
            except UnicodeDecodeError as e:
                logger.debug('invalid input utf8', e)
            except Exception as e:
                logger.warning('exception in API client', e)
                write_stream.close()
                return

    def handle_command(self, line: str, write_stream: asyncio.StreamWriter) -> None:
        words = line.split()
        if len(words) == 0:
            return

        command = words[0]
        command_args = words[1:]
        if command == 'probe' and args.discovery:
            intf = command_args[0] if command_args else None
            logger.debug('probing devices on {} upon request'.format(intf))
            for client in self.get_clients_by_interface(intf):
                client.send_probe()
        elif command == 'clear' and args.discovery:
            logger.debug('clearing list of known devices')
            WSDDiscoveredDevice.instances.clear()
        elif command == 'list' and args.discovery:
            wsd_type = command_args[0] if command_args else None
            write_stream.write(bytes(self.get_list_reply(wsd_type), 'utf-8'))
        elif command == 'quit':
            write_stream.close()
        elif command == 'start':
            self.address_monitor.enumerate()
        elif command == 'stop':
            self.address_monitor.teardown()
        else:
            logger.debug('could not handle API request: {}'.format(line))

    def get_clients_by_interface(self, interface: Optional[str]) -> List[WSDClient]:
        return [c for c in WSDClient.instances if c.mch.address.interface.name == interface or not interface]

    def get_list_reply(self, wsd_type: Optional[str]) -> str:
        retval = ''
        for dev_uuid, dev in WSDDiscoveredDevice.instances.items():
            if wsd_type and (wsd_type not in dev.types):
                continue

            addrs_str = []
            for addrs in dev.addresses.items():
                addrs_str.append(', '.join(['{}'.format(a) for a in addrs]))

            retval = retval + '{}\t{}\t{}\t{}\t{}\t{}\n'.format(
                dev_uuid,
                dev.display_name,
                dev.props['BelongsTo'] if 'BelongsTo' in dev.props else '',
                datetime.datetime.fromtimestamp(dev.last_seen).isoformat('T', 'seconds'),
                ','.join(addrs_str),
                ','.join(dev.types))

        retval += '.\n'
        return retval

    async def cleanup(self) -> None:
        # ensure the server is not created after we have teared down
        await self.create_task
        if self.server:
            self.server.close()
            await self.server.wait_closed()


class MetaEnumAfterInit(type):

    def __call__(cls, *cargs, **kwargs):
        obj = super().__call__(*cargs, **kwargs)
        if not args.no_autostart:
            obj.enumerate()
        return obj


class NetworkAddressMonitor(metaclass=MetaEnumAfterInit):
    """
    Observes changes of network addresses, handles addition and removal of
    network addresses, and filters for addresses/interfaces that are or are not
    handled. The actual OS-specific implementation that detects the changes is
    done in subclasses. This class is used as a singleton
    """

    instance: ClassVar[object] = None

    interfaces: Dict[int, NetworkInterface]
    aio_loop: asyncio.AbstractEventLoop
    mchs: List[MulticastHandler]
    http_servers: List[WSDHttpServer]
    teardown_tasks: List[asyncio.Task]
    active: bool

    def __init__(self, aio_loop: asyncio.AbstractEventLoop) -> None:

        if NetworkAddressMonitor.instance is not None:
            raise RuntimeError('Instance of NetworkAddressMonitor already created')

        NetworkAddressMonitor.instance = self

        self.interfaces = {}
        self.aio_loop = aio_loop

        self.mchs = []
        self.http_servers = []
        self.teardown_tasks = []

        self.active = False

    def enumerate(self) -> None:
        """
        Performs an initial enumeration of addresses and sets up everything
        for observing future changes.
        """
        if self.active:
            return

        self.active = True
        self.do_enumerate()

    def do_enumerate(self) -> None:
        pass

    def handle_change(self) -> None:
        """ handle network change message """
        pass

    def add_interface(self, interface: NetworkInterface) -> NetworkInterface:
        # TODO: Cleanup
        if interface.index in self.interfaces:
            pass
            # self.interfaces[idx].name = name
        else:
            self.interfaces[interface.index] = interface

        return self.interfaces[interface.index]

    def is_address_handled(self, address: NetworkAddress) -> bool:
        # do not handle anything when we are not active
        if not self.active:
            return False

        # filter out address families we are not interested in
        if args.ipv4only and address.family != socket.AF_INET:
            return False
        if args.ipv6only and address.family != socket.AF_INET6:
            return False

        if address.is_multicastable:
            return False

        # Use interface only if it's in the list of user-provided interface names
        if ((args.interface) and (address.interface.name not in args.interface)
                and (address.address_str not in args.interface)):
            return False

        return True

    def handle_new_address(self, address: NetworkAddress) -> None:
        logger.debug('new address {}'.format(address))

        if not self.is_address_handled(address):
            logger.debug('ignoring that address on {}'.format(address.interface))
            return

        # filter out what is not wanted
        # Ignore addresses or interfaces we already handle. There can only be
        # one multicast handler per address family and network interface
        for mch in self.mchs:
            if mch.handles_address(address):
                return

        logger.debug('handling traffic for {}'.format(address))
        mch = MulticastHandler(address, self.aio_loop)
        self.mchs.append(mch)

        if not args.no_host:
            WSDHost(mch)
            if not args.no_http:
                self.http_servers.append(WSDHttpServer(mch, self.aio_loop))

        if args.discovery:
            WSDClient(mch)

    def handle_deleted_address(self, address: NetworkAddress) -> None:
        logger.info('deleted address {}'.format(address))

        if not self.is_address_handled(address):
            return

        mch: Optional[MulticastHandler] = self.get_mch_by_address(address)
        if mch is None:
            return

        # Do not tear the client/hosts down. Saying goodbye does not work
        # because the address is already gone (at least on Linux).
        for c in WSDClient.instances:
            if c.mch == mch:
                c.cleanup()
                break
        for h in WSDHost.instances:
            if h.mch == mch:
                h.cleanup()
                break
        for s in self.http_servers:
            if s.mch == mch:
                s.server_close()
                self.http_servers.remove(s)

        mch.cleanup()
        self.mchs.remove(mch)

    def teardown(self) -> None:
        if not self.active:
            return

        self.active = False

        # return if we are still in tear down process
        if len(self.teardown_tasks) > 0:
            return

        for h in WSDHost.instances:
            h.teardown()
            h.cleanup()
            self.teardown_tasks.extend(h.pending_tasks)

        for c in WSDClient.instances:
            c.teardown()
            c.cleanup()
            self.teardown_tasks.extend(c.pending_tasks)

        for s in self.http_servers:
            s.server_close()

        self.http_servers.clear()

        if not self.teardown_tasks:
            return

        if not self.aio_loop.is_running():
            # Wait here for all pending tasks so that the main loop can be finished on termination.
            self.aio_loop.run_until_complete(asyncio.gather(*self.teardown_tasks))
        else:
            for t in self.teardown_tasks:
                t.add_done_callback(self.mch_teardown)

    def mch_teardown(self, task) -> None:
        if any([not t.done() for t in self.teardown_tasks]):
            return

        self.teardown_tasks.clear()

        for mch in self.mchs:
            mch.cleanup()
        self.mchs.clear()

    def cleanup(self) -> None:
        self.teardown()

    def get_mch_by_address(self, address: NetworkAddress) -> Optional[MulticastHandler]:
        """
        Get the MCI for the address, its family and the interface.
        adress must be given as a string.
        """
        for retval in self.mchs:
            if retval.handles_address(address):
                return retval

        return None


# from rtnetlink.h
RTMGRP_LINK: int = 1
RTMGRP_IPV4_IFADDR: int = 0x10
RTMGRP_IPV6_IFADDR: int = 0x100

# from netlink.h (struct nlmsghdr)
NLM_HDR_DEF: str = '@IHHII'

NLM_F_REQUEST: int = 0x01
NLM_F_ROOT: int = 0x100
NLM_F_MATCH: int = 0x200
NLM_F_DUMP: int = NLM_F_ROOT | NLM_F_MATCH

# self defines
NLM_HDR_ALIGNTO: int = 4

# ifa flags
IFA_F_DADFAILED: int = 0x08
IFA_F_HOMEADDRESS: int = 0x10
IFA_F_DEPRECATED: int = 0x20
IFA_F_TENTATIVE: int = 0x40

# from if_addr.h (struct ifaddrmsg)
IFADDR_MSG_DEF: str = '@BBBBI'
IFA_ADDRESS: int = 1
IFA_LOCAL: int = 2
IFA_LABEL: int = 3
IFA_FLAGS: int = 8
IFA_MSG_LEN: int = 8

RTA_ALIGNTO: int = 4
RTA_LEN: int = 4


def align_to(x: int, n: int) -> int:
    return ((x + n - 1) // n) * n


class NetlinkAddressMonitor(NetworkAddressMonitor):
    """
    Implementation of the AddressMonitor for Netlink sockets, i.e. Linux
    """

    RTM_NEWADDR: int = 20
    RTM_DELADDR: int = 21
    RTM_GETADDR: int = 22

    socket: socket.socket

    def __init__(self, aio_loop: asyncio.AbstractEventLoop) -> None:
        super().__init__(aio_loop)

        rtm_groups = RTMGRP_LINK
        if not args.ipv4only:
            rtm_groups = rtm_groups | RTMGRP_IPV6_IFADDR
        if not args.ipv6only:
            rtm_groups = rtm_groups | RTMGRP_IPV4_IFADDR

        self.socket = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, socket.NETLINK_ROUTE)
        self.socket.bind((0, rtm_groups))
        self.aio_loop.add_reader(self.socket.fileno(), self.handle_change)

        self.NLM_HDR_LEN = struct.calcsize(NLM_HDR_DEF)

    def do_enumerate(self) -> None:
        super().do_enumerate()

        kernel = (0, 0)
        # Append an unsigned byte to the header for the request.
        req = struct.pack(NLM_HDR_DEF + 'B', self.NLM_HDR_LEN + 1, self.RTM_GETADDR,
                          NLM_F_REQUEST | NLM_F_DUMP, 1, 0, socket.AF_PACKET)
        self.socket.sendto(req, kernel)

    def handle_change(self) -> None:
        super().handle_change()

        buf, src = self.socket.recvfrom(4096)
        logger.debug('netlink message with {} bytes'.format(len(buf)))

        offset = 0
        while offset < len(buf):
            h_len, h_type, _, _, _ = struct.unpack_from(NLM_HDR_DEF, buf, offset)
            offset += self.NLM_HDR_LEN

            msg_len = h_len - self.NLM_HDR_LEN
            if msg_len < 0:
                break

            if h_type != self.RTM_NEWADDR and h_type != self.RTM_DELADDR:
                logger.debug('invalid rtm_message type {}'.format(h_type))
                offset += align_to(msg_len, NLM_HDR_ALIGNTO)
                continue

            # decode ifaddrmsg as in if_addr.h
            ifa_family, _, ifa_flags, ifa_scope, ifa_idx = struct.unpack_from(IFADDR_MSG_DEF, buf, offset)
            if ((ifa_flags & IFA_F_DADFAILED) or (ifa_flags & IFA_F_HOMEADDRESS)
                    or (ifa_flags & IFA_F_DEPRECATED) or (ifa_flags & IFA_F_TENTATIVE)):
                logger.debug('ignore address with invalid state {}'.format(hex(ifa_flags)))
                offset += align_to(msg_len, NLM_HDR_ALIGNTO)
                continue

            logger.debug('RTM new/del addr family: {} flags: {} scope: {} idx: {}'.format(
                         ifa_family, ifa_flags, ifa_scope, ifa_idx))
            addr = None
            i = offset + IFA_MSG_LEN
            while i - offset < msg_len:
                attr_len, attr_type = struct.unpack_from('HH', buf, i)
                logger.debug('rt_attr {} {}'.format(attr_len, attr_type))

                if attr_len < RTA_LEN:
                    logger.debug('invalid rtm_attr_len. skipping remainder')
                    break

                if attr_type == IFA_LABEL:
                    name, = struct.unpack_from(str(attr_len - 4 - 1) + 's', buf, i + 4)
                    self.add_interface(NetworkInterface(name.decode(), ifa_scope, ifa_idx))
                elif attr_type == IFA_LOCAL and ifa_family == socket.AF_INET:
                    addr = buf[i + 4:i + 4 + 4]
                elif attr_type == IFA_ADDRESS and ifa_family == socket.AF_INET6:
                    addr = buf[i + 4:i + 4 + 16]
                elif attr_type == IFA_FLAGS:
                    _, ifa_flags = struct.unpack_from('HI', buf, i)
                i += align_to(attr_len, RTA_ALIGNTO)

            if addr is None:
                logger.debug('no address in RTM message')
                offset += align_to(msg_len, NLM_HDR_ALIGNTO)
                continue

            # In case of IPv6 only addresses, there appears to be no IFA_LABEL
            # message. Therefore, the name is requested by other means (#94)
            if ifa_idx not in self.interfaces:
                try:
                    logger.debug('unknown interface name for idx {}. resolving manually'.format(ifa_idx))
                    if_name = socket.if_indextoname(ifa_idx)
                    self.add_interface(NetworkInterface(if_name, ifa_scope, ifa_idx))
                except OSError:
                    logger.exception('interface detection failed')
                    # accept this exception (which should not occur)
                    pass

            # In case really strange things happen and we could not find out the
            # interface name for the returned ifa_idx, we... log a message.
            if ifa_idx in self.interfaces:
                address = NetworkAddress(ifa_family, addr, self.interfaces[ifa_idx])
                if h_type == self.RTM_NEWADDR:
                    self.handle_new_address(address)
                elif h_type == self.RTM_DELADDR:
                    self.handle_deleted_address(address)
            else:
                logger.debug('unknown interface index: {}'.format(ifa_idx))

            offset += align_to(msg_len, NLM_HDR_ALIGNTO)

    def cleanup(self) -> None:
        self.aio_loop.remove_reader(self.socket.fileno())
        self.socket.close()
        super().cleanup()


# from sys/net/route.h
RTA_IFA: int = 0x20

# from sys/socket.h
CTL_NET: int = 4
NET_RT_IFLIST: int = 3

# from sys/net/if.h
IFF_LOOPBACK: int = 0x8
IFF_MULTICAST: int = 0x800 if platform.system() != 'OpenBSD' else 0x8000

# sys/netinet6/in6_var.h
IN6_IFF_TENTATIVE: int = 0x02
IN6_IFF_DUPLICATED: int = 0x04
IN6_IFF_NOTREADY: int = IN6_IFF_TENTATIVE | IN6_IFF_DUPLICATED

SA_ALIGNTO: int = ctypes.sizeof(ctypes.c_long) if platform.system() != "Darwin" else ctypes.sizeof(ctypes.c_uint32)


class RouteSocketAddressMonitor(NetworkAddressMonitor):
    """
    Implementation of the AddressMonitor for FreeBSD and Darwin using route sockets
    """

    # Common definition for beginning part of if(m?a)?_msghdr structs (see net/if.h/man 4 route).
    IF_COMMON_HDR_DEF = '@HBBii' if platform.system() != 'OpenBSD' else '@HBBHHHBBiii'

    # from net/if.h
    RTM_NEWADDR: int = 0xC
    RTM_DELADDR: int = 0xD
    # not tested for OpenBSD
    RTM_IFINFO: int = 0xE

    # from route.h (value equals for FreeBSD, Darwin and OpenBSD)
    RTM_VERSION: int = 0x5

    # from net/if.h (struct ifa_msghdr)
    IFA_MSGHDR_DEF: str = IF_COMMON_HDR_DEF + ('hi' if platform.system() != 'OpenBSD' else '')
    IFA_MSGHDR_SIZE: int = struct.calcsize(IFA_MSGHDR_DEF)

    # The struct package does not allow to specify those, thus we hard code them as chars (x4).
    IF_MSG_DEFS: Dict[str, str] = {
        # if_data in if_msghdr is prepended with an u_short _ifm_spare1, thus the 'H' a the beginning)
        'FreeBSD': 'hH6c2c8c8c104c8c16c',
        # There are 8 bytes and 22 uint32_t in the if_data struct (22 x 4 Bytes + 8 = 96 Bytes)
        # It is also aligned on 4-byte boundary necessitating 2 bytes padding inside if_msghdr
        'Darwin': 'h2c8c22I',
        # struct if_data from /src/sys/net/if.h for if_msghdr
        #  (includes struct timeval which is a int64 + long
        'OpenBSD': '4c3I13Q1Iql'
    }

    socket: socket.socket
    intf_blacklist: List[str]

    is_openbsd: bool = False

    def __init__(self, aio_loop: asyncio.AbstractEventLoop) -> None:
        super().__init__(aio_loop)
        self.intf_blacklist = []

        # Create routing socket to get notified about future changes.
        # Do this before fetching the current routing information to avoid race condition.
        self.socket = socket.socket(socket.AF_ROUTE, socket.SOCK_RAW, socket.AF_UNSPEC)
        self.aio_loop.add_reader(self.socket.fileno(), self.handle_change)

        self.IF_MSGHDR_SIZE = struct.calcsize(self.IF_COMMON_HDR_DEF + self.IF_MSG_DEFS[platform.system()])
        self.is_openbsd = platform.system() == 'OpenBSD'

    def do_enumerate(self) -> None:
        super().do_enumerate()
        mib = [CTL_NET, socket.AF_ROUTE, 0, 0, NET_RT_IFLIST, 0]
        rt_mib = (ctypes.c_int * len(mib))()
        rt_mib[:] = [ctypes.c_int(m) for m in mib]

        libc = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True)

        # Ask kernel for routing table size first.
        rt_size = ctypes.c_size_t()
        if libc.sysctl(ctypes.byref(rt_mib), ctypes.c_size_t(len(rt_mib)), 0, ctypes.byref(rt_size), 0, 0):
            raise OSError(ctypes.get_errno(), os.strerror(ctypes.get_errno()))

        # Get the initial routing (interface list) data.
        rt_buf = ctypes.create_string_buffer(rt_size.value)
        if libc.sysctl(ctypes.byref(rt_mib), ctypes.c_size_t(len(rt_mib)), rt_buf, ctypes.byref(rt_size), 0, 0):
            raise OSError(ctypes.get_errno(), os.strerror(ctypes.get_errno()))

        self.parse_route_socket_response(rt_buf.raw, True)

    def handle_change(self) -> None:
        super().handle_change()

        self.parse_route_socket_response(self.socket.recv(4096), False)

    def parse_route_socket_response(self, buf: bytes, keep_intf: bool) -> None:
        offset = 0

        intf = None
        intf_flags = 0
        while offset < len(buf):
            # unpack route message response
            if not self.is_openbsd:
                rtm_len, rtm_version, rtm_type, addr_mask, flags = struct.unpack_from(
                    self.IF_COMMON_HDR_DEF, buf, offset)
            else:
                rtm_len, rtm_version, rtm_type, ifa_hdr_len, _, _, _, _, addr_mask, flags, _ = struct.unpack_from(
                    self.IF_COMMON_HDR_DEF, buf, offset)

            # exit condition for OpenBSD where always the complete buffer (ie 4096 bytes) is returned
            if rtm_len == 0:
                break

            # skip over non-understood packets and versions
            if (rtm_type not in [self.RTM_NEWADDR, self.RTM_DELADDR, self.RTM_IFINFO]) or (
                    rtm_version != self.RTM_VERSION):
                offset += rtm_len
                continue

            if rtm_type == self.RTM_IFINFO:
                intf_flags = flags

            sa_offset = offset + (self.IF_MSGHDR_SIZE if rtm_type == self.RTM_IFINFO else self.IFA_MSGHDR_SIZE)

            # For a route socket message, and different to a sysctl response,
            # the link info is stored inside the same rtm message, so it has to
            # survive multiple rtm messages in such cases
            if not keep_intf:
                intf = None

            new_intf = self.parse_addrs(buf, sa_offset, offset + rtm_len, intf, addr_mask, rtm_type, intf_flags)
            intf = new_intf if new_intf else intf

            offset += rtm_len

    def clear_addr_scope(self, raw_addr: bytes) -> bytes:
        addr: bytearray = bytearray(raw_addr)
        # adapted from in6_clearscope BSD/Mac kernel method (see scope6.c)
        if addr[0] == 0xfe and (addr[1] & 0xc0) == 0x80:
            addr[2] = 0
            addr[3] = 0

        return bytes(addr)

    def parse_addrs(self, buf: bytes, offset: int, limit: int, intf: Optional[NetworkInterface], addr_mask: int,
                    rtm_type: int, flags: int) -> Optional[NetworkInterface]:
        addr_type_idx = 1
        addr = None
        addr_family: int = socket.AF_UNSPEC
        while offset < limit:
            while not (addr_type_idx & addr_mask) and (addr_type_idx <= addr_mask):
                addr_type_idx = addr_type_idx << 1

            sa_len, sa_fam = struct.unpack_from('@BB', buf, offset)
            if sa_fam in [socket.AF_INET, socket.AF_INET6] and addr_type_idx == RTA_IFA:
                addr_family = sa_fam
                addr_offset = 4 if sa_fam == socket.AF_INET else 8
                addr_length = 4 if sa_fam == socket.AF_INET else 16
                addr_start = offset + addr_offset
                addr = buf[addr_start:addr_start + addr_length]
                if sa_fam == socket.AF_INET6:
                    addr = self.clear_addr_scope(addr)
            elif sa_fam == socket.AF_LINK:
                idx, _, name_len = struct.unpack_from('@HBB', buf, offset + 2)
                if idx > 0:
                    off_name = offset + 8
                    if_name = (buf[off_name:off_name + name_len]).decode()
                    intf = self.add_interface(NetworkInterface(if_name, idx, idx))

            offset += align_to(sa_len, SA_ALIGNTO) if sa_len > 0 else SA_ALIGNTO
            addr_type_idx = addr_type_idx << 1

        if rtm_type == self.RTM_IFINFO and intf is not None:
            if flags & IFF_LOOPBACK or not flags & IFF_MULTICAST:
                self.intf_blacklist.append(intf.name)
            elif intf.name in self.intf_blacklist:
                self.intf_blacklist.remove(intf.name)

        if intf is None or intf.name in self.intf_blacklist or addr is None:
            return intf

        address = NetworkAddress(addr_family, addr, intf)
        if rtm_type == self.RTM_DELADDR:
            self.handle_deleted_address(address)
        else:
            # Too bad, the address may be unuseable (tentative, e.g.) here
            # but we won't get any further notifcation about the address being
            # available for use. Thus, we try and may fail here
            self.handle_new_address(address)

        return intf

    def cleanup(self) -> None:
        self.aio_loop.remove_reader(self.socket.fileno())
        self.socket.close()
        super().cleanup()


def sigterm_handler() -> None:
    logger.info('received termination/interrupt signal, tearing down')
    # implictely raise SystemExit to cleanup properly
    sys.exit(0)


def parse_args() -> None:
    global args, logger

    parser = argparse.ArgumentParser()

    parser.add_argument(
        '-i', '--interface',
        help='interface or address to use',
        action='append', default=[])
    parser.add_argument(
        '-H', '--hoplimit',
        help='hop limit for multicast packets (default = 1)', type=int,
        default=1)
    parser.add_argument(
        '-U', '--uuid',
        help='UUID for the target device',
        default=None)
    parser.add_argument(
        '-v', '--verbose',
        help='increase verbosity',
        action='count', default=0)
    parser.add_argument(
        '-d', '--domain',
        help='set domain name (disables workgroup)',
        default=None)
    parser.add_argument(
        '-n', '--hostname',
        help='override (NetBIOS) hostname to be used (default hostname)',
        # use only the local part of a possible FQDN
        default=socket.gethostname().partition('.')[0])
    parser.add_argument(
        '-w', '--workgroup',
        help='set workgroup name (default WORKGROUP)',
        default='WORKGROUP')
    parser.add_argument(
        '-A', '--no-autostart',
        help='do not start networking after launch',
        action='store_true')
    parser.add_argument(
        '-t', '--no-http',
        help='disable http service (for debugging, e.g.)',
        action='store_true')
    parser.add_argument(
        '-4', '--ipv4only',
        help='use only IPv4 (default = off)',
        action='store_true')
    parser.add_argument(
        '-6', '--ipv6only',
        help='use IPv6 (default = off)',
        action='store_true')
    parser.add_argument(
        '-s', '--shortlog',
        help='log only level and message',
        action='store_true')
    parser.add_argument(
        '-p', '--preserve-case',
        help='preserve case of the provided/detected hostname',
        action='store_true')
    parser.add_argument(
        '-c', '--chroot',
        help='directory to chroot into',
        default=None)
    parser.add_argument(
        '-u', '--user',
        help='drop privileges to user:group',
        default=None)
    parser.add_argument(
        '-D', '--discovery',
        help='enable discovery operation mode',
        action='store_true')
    parser.add_argument(
        '-l', '--listen',
        help='listen on path or localhost port in discovery mode',
        default=None)
    parser.add_argument(
        '-o', '--no-host',
        help='disable server mode operation (host will be undiscoverable)',
        action='store_true')
    parser.add_argument(
        '-V', '--version',
        help='show version number and exit',
        action='store_true')
    parser.add_argument(
        '--metadata-timeout',
        help='set timeout for HTTP-based metadata exchange',
        default=2.0)

    args = parser.parse_args(sys.argv[1:])

    if args.version:
        print('wsdd - Web Service Discovery Daemon, v{}'.format(WSDD_VERSION))
        sys.exit(0)

    if args.verbose == 1:
        log_level = logging.INFO
    elif args.verbose > 1:
        log_level = logging.DEBUG
        asyncio.get_event_loop().set_debug(True)
        logging.getLogger("asyncio").setLevel(logging.DEBUG)
    else:
        log_level = logging.WARNING

    if args.shortlog:
        fmt = '%(levelname)s: %(message)s'
    else:
        fmt = '%(asctime)s:%(name)s %(levelname)s(pid %(process)d): %(message)s'

    logging.basicConfig(level=log_level, format=fmt)
    logger = logging.getLogger('wsdd')

    if not args.interface:
        logger.warning('no interface given, using all interfaces')

    if not args.uuid:
        def read_uuid_from_file(fn: str) -> Union[None, uuid.UUID]:
            try:
                with open(fn) as f:
                    s: str = f.readline().strip()
                    return uuid.UUID(s)
            except Exception:
                return None

        # machine uuid: try machine-id file first but also check for hostid (FreeBSD)
        args.uuid = read_uuid_from_file('/etc/machine-id') or \
            read_uuid_from_file('/etc/hostid') or \
            uuid.uuid5(uuid.NAMESPACE_DNS, socket.gethostname())

        logger.info('using pre-defined UUID {0}'.format(str(args.uuid)))
    else:
        args.uuid = uuid.UUID(args.uuid)
        logger.info('user-supplied device UUID is {0}'.format(str(args.uuid)))

    for prefix, uri in namespaces.items():
        ElementTree.register_namespace(prefix, uri)


def chroot(root: str) -> bool:
    """
    Chroot into a separate directory to isolate ourself for increased security.
    """
    # preload for socket.gethostbyaddr()
    import encodings.idna

    try:
        os.chroot(root)
        os.chdir('/')
        logger.info('chrooted successfully to {}'.format(root))
    except Exception as e:
        logger.error('could not chroot to {}: {}'.format(root, e))
        return False

    return True


def get_ids_from_userspec(user_spec: str) -> Tuple[int, int]:
    uid: int
    gid: int
    try:
        user, _, group = user_spec.partition(':')

        if user:
            uid = pwd.getpwnam(user).pw_uid

        if group:
            gid = grp.getgrnam(group).gr_gid
    except Exception as e:
        raise RuntimeError('could not get uid/gid for {}: {}'.format(user_spec, e))

    return (uid, gid)


def drop_privileges(uid: int, gid: int) -> bool:
    try:
        if gid is not None:
            os.setgid(gid)
            os.setegid(gid)
            logger.debug('switched uid to {}'.format(uid))

        if uid is not None:
            os.setuid(uid)
            os.seteuid(uid)
            logger.debug('switched gid to {}'.format(gid))

        logger.info('running as {} ({}:{})'.format(args.user, uid, gid))
    except Exception as e:
        logger.error('dropping privileges failed: {}'.format(e))
        return False

    return True


def create_address_monitor(system: str, aio_loop: asyncio.AbstractEventLoop) -> NetworkAddressMonitor:
    if system == 'Linux':
        return NetlinkAddressMonitor(aio_loop)
    elif system in ['FreeBSD', 'Darwin', 'OpenBSD']:
        return RouteSocketAddressMonitor(aio_loop)
    else:
        raise NotImplementedError('unsupported OS: ' + system)


def main() -> int:
    global logger, args

    parse_args()

    if args.ipv4only and args.ipv6only:
        logger.error('Listening to no IP address family.')
        return 4

    aio_loop = asyncio.new_event_loop()
    nm = create_address_monitor(platform.system(), aio_loop)

    api_server = None
    if args.listen:
        api_server = ApiServer(aio_loop, args.listen, nm)

    # get uid:gid before potential chroot'ing
    if args.user is not None:
        ids = get_ids_from_userspec(args.user)
        if not ids:
            return 3

    if args.chroot is not None:
        if not chroot(args.chroot):
            return 2

    if args.user is not None:
        if not drop_privileges(ids[0], ids[1]):
            return 3

    if args.chroot and (os.getuid() == 0 or os.getgid() == 0):
        logger.warning('chrooted but running as root, consider -u option')

    # main loop, serve requests coming from any outbound socket
    aio_loop.add_signal_handler(signal.SIGINT, sigterm_handler)
    aio_loop.add_signal_handler(signal.SIGTERM, sigterm_handler)
    try:
        aio_loop.run_forever()
    except (SystemExit, KeyboardInterrupt):
        logger.info('shutting down gracefully...')
        if api_server is not None:
            aio_loop.run_until_complete(api_server.cleanup())

        nm.cleanup()
        aio_loop.stop()
    except Exception:
        logger.exception('error in main loop')

    logger.info('Done.')
    return 0


if __name__ == '__main__':
    sys.exit(main())

Filemanager

Name Type Size Permission Actions
X11 Folder 0755
GET File 15.87 KB 0755
HEAD File 15.87 KB 0755
POST File 15.87 KB 0755
X File 274 B 0755
Xephyr File 2.67 MB 0755
Xorg File 274 B 0755
Xwayland File 2.76 MB 0755
[ File 46.51 KB 0755
aa-enabled File 18.38 KB 0755
aa-exec File 18.38 KB 0755
aa-features-abi File 18.38 KB 0755
ab File 58.51 KB 0755
aconnect File 22.45 KB 0755
acpidbg File 1.58 KB 0755
add-apt-repository File 24.42 KB 0755
addr2line File 30.78 KB 0755
airscan-discover File 154.93 KB 0755
alsabat File 50.52 KB 0755
alsaloop File 91.41 KB 0755
alsamixer File 100.37 KB 0755
alsatplg File 86.45 KB 0755
alsaucm File 34.91 KB 0755
amidi File 30.46 KB 0755
amixer File 66.53 KB 0755
apg File 274 B 0755
apgbfm File 26.38 KB 0755
aplay File 86.5 KB 0755
aplaymidi File 26.46 KB 0755
aplaymidi2 File 22.47 KB 0755
apport-bug File 2.27 KB 0755
apport-cli File 13.56 KB 0755
apport-collect File 2.27 KB 0755
apport-unpack File 3.7 KB 0755
appres File 14.38 KB 0755
appstreamcli File 146.3 KB 0755
apropos File 47.36 KB 0755
apt File 18.46 KB 0755
apt-add-repository File 24.42 KB 0755
apt-cache File 90.54 KB 0755
apt-cdrom File 30.54 KB 0755
apt-config File 30.47 KB 0755
apt-extracttemplates File 26.53 KB 0755
apt-ftparchive File 246.55 KB 0755
apt-get File 58.54 KB 0755
apt-mark File 70.54 KB 0755
apt-sortpkgs File 42.47 KB 0755
aptdcon File 1.01 KB 0755
ar File 54.56 KB 0755
arch File 34.59 KB 0755
arecord File 86.5 KB 0755
arecordmidi File 34.47 KB 0755
arecordmidi2 File 26.48 KB 0755
arm2hpdl File 14.31 KB 0755
as File 795.52 KB 0755
aseqdump File 34.45 KB 0755
aseqnet File 22.51 KB 0755
aseqsend File 22.46 KB 0755
aspell File 162.55 KB 0755
aspell-import File 2 KB 0755
atobm File 14.3 KB 0755
awk File 190.84 KB 0755
axfer File 90.45 KB 0755
b2sum File 54.59 KB 0755
baobab File 302.52 KB 0755
base32 File 42.59 KB 0755
base64 File 42.59 KB 0755
basename File 34.59 KB 0755
basenc File 50.59 KB 0755
bash File 1.66 MB 0755
bashbug File 6.86 KB 0755
bc File 90.82 KB 0755
bdftopcf File 42.56 KB 0755
bdftruncate File 14.38 KB 0755
bitmap File 106.31 KB 0755
bluemoon File 38.45 KB 0755
bluetooth-sendto File 30.48 KB 0755
bluetoothctl File 574.27 KB 0755
bmtoa File 14.32 KB 0755
boltctl File 122.84 KB 0755
bpftrace File 4.57 MB 0755
bpftrace-aotrt File 3.2 MB 0755
brltty File 1.13 MB 0755
brltty-atb File 218.63 KB 0755
brltty-clip File 214.57 KB 0755
brltty-ctb File 330.8 KB 0755
brltty-hid File 274.84 KB 0755
brltty-ktb File 603.28 KB 0755
brltty-lscmds File 250.58 KB 0755
brltty-morse File 286.64 KB 0755
brltty-trtxt File 274.7 KB 0755
brltty-ttb File 318.88 KB 0755
brltty-tune File 302.7 KB 0755
broadwayd File 126.46 KB 0755
browse File 31.53 KB 0755
btattach File 30.45 KB 0755
btmgmt File 186.56 KB 0755
btmon File 1.16 MB 0755
btrfs File 1.49 MB 0755
btrfs-convert File 884.63 KB 0755
btrfs-find-root File 796.63 KB 0755
btrfs-image File 840.63 KB 0755
btrfs-map-logical File 796.63 KB 0755
btrfs-select-super File 792.63 KB 0755
btrfsck File 1.49 MB 0755
btrfstune File 832.63 KB 0755
bunzip2 File 38.45 KB 0755
busctl File 102.6 KB 0755
busybox File 2.34 MB 0755
bwrap File 82.54 KB 0755
bzcat File 38.45 KB 0755
bzcmp File 2.17 KB 0755
bzdiff File 2.17 KB 0755
bzegrep File 3.69 KB 0755
bzexe File 4.78 KB 0755
bzfgrep File 3.69 KB 0755
bzgrep File 3.69 KB 0755
bzip2 File 38.45 KB 0755
bzip2recover File 18.38 KB 0755
bzless File 1.27 KB 0755
bzmore File 1.27 KB 0755
c++filt File 26.34 KB 0755
c89 File 428 B 0755
c89-gcc File 428 B 0755
c99 File 454 B 0755
c99-gcc File 454 B 0755
c_rehash File 6.67 KB 0755
calibrate_ppa File 26.38 KB 0755
canberra-gtk-play File 18.3 KB 0755
cancel File 18.38 KB 0755
captoinfo File 94.49 KB 0755
cat File 42.54 KB 0755
catman File 30.84 KB 0755
cc File 1.13 MB 0755
cd-create-profile File 26.38 KB 0755
cd-fix-profile File 30.38 KB 0755
cd-iccdump File 14.38 KB 0755
cd-it8 File 26.38 KB 0755
certutil File 186.93 KB 0755
cgi-fcgi File 18.23 KB 0755
chacl File 18.3 KB 0755
chage File 83.23 KB 2755
chardet File 221 B 0755
chardetect File 221 B 0755
chattr File 14.38 KB 0755
chcon File 66.59 KB 0755
check-language-support File 2.71 KB 0755
checkgid File 14.38 KB 0755
chfn File 71.16 KB 4755
chgrp File 66.59 KB 0755
chktest File 14.38 KB 0755
chmod File 62.59 KB 0755
choom File 22.45 KB 0755
chown File 66.59 KB 0755
chrt File 30.45 KB 0755
chsh File 47.79 KB 4755
chvt File 14.45 KB 0755
cifsiostat File 26.55 KB 0755
ciptool File 38.56 KB 0755
ckbcomp File 147.14 KB 0755
cksum File 106.6 KB 0755
clear File 14.38 KB 0755
clear_console File 14.3 KB 0755
cloud-id File 972 B 0755
cloud-init File 976 B 0755
cloud-init-per File 2.06 KB 0755
cmp File 50.47 KB 0755
cmsutil File 46.47 KB 0755
codepage File 14.37 KB 0755
col File 22.46 KB 0755
colcrt File 14.46 KB 0755
colormgr File 58.45 KB 0755
colrm File 14.46 KB 0755
column File 38.46 KB 0755
comm File 38.59 KB 0755
corelist File 15.01 KB 0755
cp File 142.59 KB 0755
cpan File 8.16 KB 0755
cpan5.40-x86_64-linux-gnu File 8.18 KB 0755
cpio File 142.02 KB 0755
cpp File 1.13 MB 0755
cpp-14 File 1.13 MB 0755
cpupower File 1.58 KB 0755
crash File 13.91 MB 0755
crlutil File 98.48 KB 0755
crontab File 42.81 KB 2755
csplit File 54.59 KB 0755
ctstat File 22.73 KB 0755
cupstestppd File 74.45 KB 0755
curl File 310.48 KB 0755
cut File 42.59 KB 0755
cvt File 14.23 KB 0755
cvtsudoers File 377.3 KB 0755
dash File 146.84 KB 0755
date File 106.59 KB 0755
dbus-cleanup-sockets File 14.37 KB 0755
dbus-daemon File 242.72 KB 0755
dbus-monitor File 38.37 KB 0755
dbus-run-session File 14.37 KB 0755
dbus-send File 42.37 KB 0755
dbus-update-activation-environment File 18.37 KB 0755
dbus-uuidgen File 14.37 KB 0755
dbxtool File 22.45 KB 0755
dc File 50.24 KB 0755
dconf File 62.3 KB 0755
dd File 66.62 KB 0755
ddstdecode File 18.31 KB 0755
deallocvt File 14.45 KB 0755
deb-systemd-helper File 23.79 KB 0755
deb-systemd-invoke File 6.97 KB 0755
debconf File 2.8 KB 0755
debconf-apt-progress File 11.57 KB 0755
debconf-communicate File 623 B 0755
debconf-copydb File 1.68 KB 0755
debconf-escape File 668 B 0755
debconf-set-selections File 3.14 KB 0755
debconf-show File 1.78 KB 0755
debian-distro-info File 31.03 KB 0755
deja-dup File 402.59 KB 0755
delv File 61.4 KB 0755
derdump File 30.46 KB 0755
desktop-file-edit File 96.57 KB 0755
desktop-file-install File 96.57 KB 0755
desktop-file-validate File 80.85 KB 0755
df File 79.06 KB 0755
dh_bash-completion File 4.42 KB 0755
dh_installxmlcatalogs File 9.22 KB 0755
dh_perl_openssl File 1.53 KB 0755
diff File 154.63 KB 0755
diff3 File 66.59 KB 0755
dig File 154.95 KB 0755
dir File 155.02 KB 0755
dircolors File 46.59 KB 0755
dirmngr File 545.84 KB 0755
dirmngr-client File 55 KB 0755
dirname File 34.46 KB 0755
distro-info File 26.97 KB 0755
dmesg File 80.78 KB 0755
dnsdomainname File 22.3 KB 0755
do-release-upgrade File 9.05 KB 0755
domainname File 22.3 KB 0755
dpkg File 371.2 KB 0755
dpkg-deb File 162.66 KB 0755
dpkg-divert File 134.82 KB 0755
dpkg-maintscript-helper File 20.63 KB 0755
dpkg-query File 158.84 KB 0755
dpkg-realpath File 38.45 KB 0755
dpkg-split File 110.61 KB 0755
dpkg-statoverride File 54.63 KB 0755
dpkg-trigger File 46.61 KB 0755
driverless File 30.47 KB 0755
driverless-fax File 591 B 0755
du File 106.6 KB 0755
dumpkeys File 162.93 KB 0755
duplicity File 968 B 0755
dvipdf File 1007 B 0755
eatmydata File 2.74 KB 0755
ec2metadata File 8.38 KB 0755
echo File 34.46 KB 0755
ed File 70.63 KB 0755
editor File 328.65 KB 0755
editres File 72.77 KB 0755
efibootdump File 22.38 KB 0755
efibootmgr File 47.77 KB 0755
egrep File 41 B 0755
eject File 42.3 KB 0755
elfedit File 34.79 KB 0755
enc2xs File 40.97 KB 0755
encguess File 2.99 KB 0755
enchant-2 File 22.38 KB 0755
enchant-lsmod-2 File 14.38 KB 0755
env File 50.99 KB 0755
envsubst File 38.46 KB 0755
eog File 14.45 KB 0755
eps2eps File 639 B 0755
eqn File 204.52 KB 0755
esc-m File 14.16 KB 0755
eutp File 26.23 KB 0755
ex File 2.16 MB 0755
expand File 38.61 KB 0755
expiry File 22.63 KB 2755
expr File 46.49 KB 0755
factor File 70.59 KB 0755
fallocate File 26.45 KB 0755
false File 34.46 KB 0755
fc-cache File 22.45 KB 0755
fc-cat File 18.45 KB 0755
fc-conflist File 14.45 KB 0755
fc-list File 14.45 KB 0755
fc-match File 14.45 KB 0755
fc-pattern File 14.45 KB 0755
fc-query File 14.45 KB 0755
fc-scan File 14.45 KB 0755
fc-validate File 14.45 KB 0755
fcgistarter File 14.38 KB 0755
fgconsole File 14.45 KB 0755
fgrep File 41 B 0755
file File 30.6 KB 0755
file-roller File 562.61 KB 0755
file2brl File 26.3 KB 0755
find File 207.55 KB 0755
findmnt File 75.92 KB 0755
firefox File 2.32 KB 0755
flock File 26.56 KB 0755
fmt File 42.59 KB 0755
fold File 38.59 KB 0755
fonttosfnt File 46.48 KB 0755
foo2ddst File 34.96 KB 0755
foo2ddst-wrapper File 16.86 KB 0755
foo2hbpl2 File 30.98 KB 0755
foo2hbpl2-wrapper File 17.91 KB 0755
foo2hiperc File 42.99 KB 0755
foo2hiperc-wrapper File 18.11 KB 0755
foo2hp File 42.96 KB 0755
foo2hp2600-wrapper File 18.75 KB 0755
foo2lava File 42.99 KB 0755
foo2lava-wrapper File 19.61 KB 0755
foo2oak File 34.9 KB 0755
foo2oak-wrapper File 17.45 KB 0755
foo2qpdl File 43.02 KB 0755
foo2qpdl-wrapper File 19.06 KB 0755
foo2slx File 30.99 KB 0755
foo2slx-wrapper File 17.19 KB 0755
foo2xqx File 34.99 KB 0755
foo2xqx-wrapper File 17.16 KB 0755
foo2zjs File 43 KB 0755
foo2zjs-icc2ps File 14.39 KB 0755
foo2zjs-pstops File 2.93 KB 0755
foo2zjs-wrapper File 25.34 KB 0755
foomatic-rip File 115.48 KB 0755
fprintd-delete File 94.45 KB 0755
fprintd-enroll File 94.94 KB 0755
fprintd-list File 90.45 KB 0755
fprintd-verify File 90.45 KB 0755
free File 26.45 KB 0755
ftp File 182.9 KB 0755
funzip File 26.45 KB 0755
fuser File 43.42 KB 0755
fusermount File 38.45 KB 4755
fusermount3 File 38.45 KB 4755
fwupdmgr File 122.38 KB 0755
fwupdtool File 130.38 KB 0755
gamemoded File 166.73 KB 0755
gamma4scanimage File 14.38 KB 0755
gapplication File 22.46 KB 0755
gatttool File 126.56 KB 0755
gcalccmd File 286.46 KB 0755
gcc File 1.13 MB 0755
gcc-14 File 1.13 MB 0755
gcc-ar File 30.66 KB 0755
gcc-ar-14 File 30.66 KB 0755
gcc-nm File 30.66 KB 0755
gcc-nm-14 File 30.66 KB 0755
gcc-ranlib File 30.66 KB 0755
gcc-ranlib-14 File 30.66 KB 0755
gcore File 3.62 KB 0755
gcov File 468.19 KB 0755
gcov-14 File 468.19 KB 0755
gcov-dump File 380.14 KB 0755
gcov-dump-14 File 380.14 KB 0755
gcov-tool File 408.23 KB 0755
gcov-tool-14 File 408.23 KB 0755
gcr-viewer File 14.37 KB 0755
gcr-viewer-gtk4 File 34.45 KB 0755
gdb File 11.23 MB 0755
gdb-add-index File 4.55 KB 0755
gdbtui File 126 B 0755
gdbus File 54.46 KB 0755
gdctl File 51.15 KB 0755
gdk-pixbuf-csource File 14.4 KB 0755
gdk-pixbuf-pixdata File 14.38 KB 0755
gdk-pixbuf-thumbnailer File 18.47 KB 0755
gdm-config File 50.75 KB 0755
gdmflexiserver File 22.94 KB 0755
gencat File 34.52 KB 0755
geqn File 204.52 KB 0755
getconf File 26.44 KB 0755
getent File 38.8 KB 0755
getfacl File 30.38 KB 0755
getkeycodes File 14.45 KB 0755
getopt File 22.45 KB 0755
gettext File 38.46 KB 0755
gettext.sh File 5.05 KB 0755
ghostscript File 14.23 KB 0755
ginstall-info File 47.31 KB 0755
gio File 110.48 KB 0755
gio-querymodules File 18.38 KB 0755
gipddecode File 18.31 KB 0755
gjs File 22.71 KB 0755
gjs-console File 22.71 KB 0755
glib-compile-schemas File 54.46 KB 0755
gmake File 344.14 KB 0755
gnome-calculator File 822.91 KB 0755
gnome-calendar File 884.62 KB 0755
gnome-characters File 253 B 0755
gnome-clocks File 458.65 KB 0755
gnome-control-center File 4.28 MB 0755
gnome-disk-image-mounter File 22.46 KB 0755
gnome-disks File 687.57 KB 0755
gnome-extensions File 78.53 KB 0755
gnome-font-viewer File 82.73 KB 0755
gnome-help File 58.3 KB 0755
gnome-keyring File 22.62 KB 0755
gnome-keyring-3 File 22.62 KB 0755
gnome-keyring-daemon File 1.07 MB 0755
gnome-language-selector File 1.41 KB 0755
gnome-logs File 170.88 KB 0755
gnome-power-statistics File 66.43 KB 0755
gnome-session File 958 B 0755
gnome-session-inhibit File 22.38 KB 0755
gnome-session-properties File 66.41 KB 0755
gnome-session-quit File 14.68 KB 0755
gnome-shell File 30.8 KB 0755
gnome-shell-extension-tool File 1.67 KB 0755
gnome-shell-test-tool File 11.12 KB 0755
gnome-system-monitor File 427.49 KB 0755
gnome-terminal File 91.78 KB 0755
gnome-terminal.wrapper File 6.06 KB 0755
gnome-text-editor File 654.7 KB 0755
gnome-thumbnail-font File 26.47 KB 0755
gnome-www-browser File 2.32 KB 0755
gp-archive File 34.59 KB 0755
gp-collect-app File 54.42 KB 0755
gp-display-html File 630.35 KB 0755
gp-display-src File 30.41 KB 0755
gp-display-text File 166.42 KB 0755
gpasswd File 78.54 KB 4755
gpg File 1.3 MB 0755
gpg-agent File 397.59 KB 0755
gpg-connect-agent File 87.38 KB 0755
gpg-wks-client File 147.44 KB 0755
gpgconf File 119.44 KB 0755
gpgparsemail File 34.38 KB 0755
gpgsm File 577.44 KB 0755
gpgsplit File 26.62 KB 0755
gpgtar File 75.91 KB 0755
gpgv File 355.22 KB 0755
gpic File 228.12 KB 0755
gprof File 99.86 KB 0755
gprofng File 22.41 KB 0755
gprofng-archive File 34.59 KB 0755
gprofng-collect-app File 54.42 KB 0755
gprofng-display-html File 630.35 KB 0755
gprofng-display-src File 30.41 KB 0755
gprofng-display-text File 166.42 KB 0755
gpu-manager File 66.9 KB 0755
grdctl File 74.46 KB 0755
grep File 182.45 KB 0755
gresource File 26.38 KB 0755
groff File 102.58 KB 0755
grog File 18.75 KB 0755
grops File 202.62 KB 0755
grotty File 130.58 KB 0755
groups File 38.59 KB 0755
growpart File 29.19 KB 0755
grub-editenv File 401.24 KB 0755
grub-file File 749.96 KB 0755
grub-fstest File 871.4 KB 0755
grub-glue-efi File 102.96 KB 0755
grub-kbdcomp File 1.64 KB 0755
grub-menulst2cfg File 87.27 KB 0755
grub-mkfont File 131.52 KB 0755
grub-mkimage File 381.34 KB 0755
grub-mklayout File 107.3 KB 0755
grub-mknetdir File 437.85 KB 0755
grub-mkpasswd-pbkdf2 File 115.4 KB 0755
grub-mkrelpath File 259.87 KB 0755
grub-mkrescue File 1.01 MB 0755
grub-mkstandalone File 522.24 KB 0755
grub-mount File 694.29 KB 0755
grub-render-label File 766.3 KB 0755
grub-script-check File 126.84 KB 0755
grub-syslinux2cfg File 706.79 KB 0755
gs File 14.23 KB 0755
gsbj File 350 B 0755
gsdj File 352 B 0755
gsdj500 File 352 B 0755
gsettings File 30.38 KB 0755
gslj File 353 B 0755
gslp File 350 B 0755
gsnd File 277 B 0755
gst-device-monitor-1.0 File 22.4 KB 0755
gst-discoverer-1.0 File 38.48 KB 0755
gst-inspect-1.0 File 66.55 KB 0755
gst-launch-1.0 File 38.48 KB 0755
gst-play-1.0 File 54.48 KB 0755
gst-stats-1.0 File 34.46 KB 0755
gst-tester-1.0 File 18.38 KB 0755
gst-typefind-1.0 File 18.46 KB 0755
gstack File 2.98 KB 0755
gstreamer-codec-install File 22.23 KB 0755
gtbl File 154.55 KB 0755
gted File 654.7 KB 0755
gtf File 18.38 KB 0755
gtk-builder-tool File 34.8 KB 0755
gtk-encode-symbolic-svg File 22.48 KB 0755
gtk-launch File 18.53 KB 0755
gtk-query-settings File 14.38 KB 0755
gtk-update-icon-cache File 42.65 KB 0755
gtk4-broadwayd File 150.46 KB 0755
gtk4-builder-tool File 82.79 KB 0755
gtk4-encode-symbolic-svg File 11.71 MB 0755
gtk4-image-tool File 38.55 KB 0755
gtk4-launch File 18.53 KB 0755
gtk4-path-tool File 50.45 KB 0755
gtk4-query-settings File 14.38 KB 0755
gtk4-rendernode-tool File 46.45 KB 0755
gtk4-update-icon-cache File 42.65 KB 0755
gunzip File 2.28 KB 0755
gzexe File 6.29 KB 0755
gzip File 123.32 KB 0755
h2ph File 28.15 KB 0755
h2xs File 59.51 KB 0755
hardlink File 46.56 KB 0755
hbpldecode File 30.39 KB 0755
hciattach File 60.53 KB 0755
hciconfig File 158.56 KB 0755
hcitool File 166.16 KB 0755
hd File 54.47 KB 0755
head File 46.59 KB 0755
heif-thumbnailer File 34.4 KB 0755
helpztags File 2.46 KB 0755
hex2hcd File 18.45 KB 0755
hexdump File 54.47 KB 0755
hipercdecode File 18.31 KB 0755
host File 118.97 KB 0755
hostid File 34.59 KB 0755
hostname File 22.3 KB 0755
hostnamectl File 34.46 KB 0755
hp-align File 9.14 KB 0755
hp-check File 39.2 KB 0755
hp-clean File 7.05 KB 0755
hp-colorcal File 9.08 KB 0755
hp-config_usb_printer File 6.98 KB 0755
hp-doctor File 12.69 KB 0755
hp-firmware File 6.47 KB 0755
hp-info File 6.26 KB 0755
hp-levels File 6.85 KB 0755
hp-logcapture File 12.15 KB 0755
hp-makeuri File 5.6 KB 0755
hp-pkservice File 3.13 KB 0755
hp-plugin File 13.62 KB 0755
hp-plugin-ubuntu File 719 B 0755
hp-probe File 7.98 KB 0755
hp-query File 4.94 KB 0755
hp-scan File 88.25 KB 0755
hp-setup File 37.26 KB 0755
hp-testpage File 5.98 KB 0755
hp-timedate File 3.31 KB 0755
htcacheclean File 38.39 KB 0755
htdbm File 26.38 KB 0755
htdigest File 14.38 KB 0755
htpasswd File 30.38 KB 0755
httpserv File 38.4 KB 0755
hwe-support-status File 11.24 KB 0755
i386 File 26.73 KB 0755
ibd2sdi File 278.98 KB 0755
ibus File 86.45 KB 0755
ibus-daemon File 230.5 KB 0755
ibus-setup File 1.15 KB 0755
ibus-table-createdb File 1.11 KB 0755
iceauth File 42.5 KB 0755
ico File 50.44 KB 0755
iconv File 66.59 KB 0755
id File 42.59 KB 0755
iecset File 26.45 KB 0755
ijs_pxljr File 34.53 KB 0755
im-config File 11.03 KB 0755
im-launch File 2.07 KB 0755
inetutils-telnet File 221.9 KB 0755
info File 245.8 KB 0755
infobrowser File 245.8 KB 0755
infocmp File 70.45 KB 0755
infotocap File 94.49 KB 0755
innochecksum File 179.63 KB 0755
inputattach File 33.75 KB 0755
install File 142.59 KB 0755
install-info File 47.31 KB 0755
instmodsh File 4.27 KB 0755
intel-virtual-output File 66.31 KB 0755
ionice File 18.45 KB 0755
iostat File 58.55 KB 0755
ip File 904.97 KB 0755
ipcmk File 22.52 KB 0755
ipcrm File 18.45 KB 0755
ipcs File 38.45 KB 0755
ipod-read-sysinfo-extended File 22.38 KB 0755
ipod-time-sync File 14.38 KB 0755
ippfind File 46.48 KB 0755
ipptool File 106.38 KB 0755
iptables-xml File 105.02 KB 0755
ischroot File 14.55 KB 0755
isdv4-serial-debugger File 18.31 KB 0755
isdv4-serial-inputattach File 18.31 KB 0755
ispell-wrapper File 7.05 KB 0755
join File 54.63 KB 0755
journalctl File 91.19 KB 0755
jpgicc File 38.47 KB 0755
jq File 34.23 KB 0755
json-patch-jsondiff File 1004 B 0755
json_pp File 4.9 KB 0755
jsondiff File 1004 B 0755
jsonpatch File 3.77 KB 0755
jsonpointer File 1.79 KB 0755
jsonschema File 213 B 0755
kbd_mode File 14.74 KB 0755
kbdinfo File 18.45 KB 0755
kbxutil File 70.91 KB 0755
kernel-install File 54.71 KB 0755
kill File 22.45 KB 0755
killall File 31.42 KB 0755
kmod File 194.31 KB 0755
kmodsign File 18.45 KB 0755
l2ping File 18.38 KB 0755
l2test File 34.72 KB 0755
laptop-detect File 3.74 KB 0755
lavadecode File 22.39 KB 0755
ld File 1.78 MB 0755
ld.bfd File 1.78 MB 0755
ld.so File 245.65 KB 0755
ldapadd File 66.53 KB 0755
ldapcompare File 66.53 KB 0755
ldapdelete File 66.55 KB 0755
ldapexop File 66.53 KB 0755
ldapmodify File 66.53 KB 0755
ldapmodrdn File 62.53 KB 0755
ldappasswd File 66.53 KB 0755
ldapsearch File 102.55 KB 0755
ldapurl File 14.38 KB 0755
ldapwhoami File 62.53 KB 0755
ldd File 5.26 KB 0755
less File 216.21 KB 0755
lessecho File 14.38 KB 0755
lessfile File 8.83 KB 0755
lesskey File 23.79 KB 0755
lesspipe File 8.83 KB 0755
lexgrog File 111.59 KB 0755
libnetcfg File 15.41 KB 0755
libreoffice File 6.5 KB 0755
link File 34.59 KB 0755
linkicc File 26.45 KB 0755
linux-boot-prober File 1.54 KB 0755
linux-check-removal File 4.56 KB 0755
linux-update-symlinks File 6.35 KB 0755
linux-version File 2.63 KB 0755
linux32 File 26.73 KB 0755
linux64 File 26.73 KB 0755
listres File 14.8 KB 0755
ln File 62.59 KB 0755
lnstat File 22.73 KB 0755
loadkeys File 206.98 KB 0755
loadunimap File 34.54 KB 0755
localc File 59 B 0755
locale File 49.71 KB 0755
locale-check File 14.23 KB 0755
localectl File 30.45 KB 0755
localedef File 323.2 KB 0755
localsearch File 133.8 KB 0755
lodraw File 59 B 0755
loffice File 53 B 0755
lofromtemplate File 64 B 0755
logger File 39.05 KB 0755
login File 42.45 KB 0755
loginctl File 66.59 KB 0755
logname File 34.59 KB 0755
logresolve File 14.39 KB 0755
loimpress File 62 B 0755
lomath File 59 B 0755
look File 18.46 KB 0755
loweb File 58 B 0755
lowntfs-3g File 131.05 KB 0755
lowriter File 61 B 0755
lp File 26.38 KB 0755
lpoptions File 22.45 KB 0755
lpq File 22.45 KB 0755
lpr File 22.38 KB 0755
lprm File 14.38 KB 0755
lpstat File 38.7 KB 0755
ls File 155.02 KB 0755
lsattr File 14.38 KB 0755
lsb_release File 2.77 KB 0755
lsblk File 178.46 KB 0755
lscpu File 118.46 KB 0755
lshw File 784.49 KB 0755
lsinitramfs File 735 B 0755
lsipc File 54.45 KB 0755
lslocks File 42.88 KB 0755
lslogins File 50.45 KB 0755
lsmem File 38.45 KB 0755
lsmod File 194.31 KB 0755
lsns File 42.46 KB 0755
lsof File 203.8 KB 0755
lspci File 144.19 KB 0755
lspgpot File 1.06 KB 0755
lspower File 1.2 KB 0755
lsusb File 234.48 KB 0755
lto-dump File 31.61 MB 0755
lto-dump-14 File 31.61 MB 0755
luit File 100.88 KB 0755
lwp-download File 10.05 KB 0755
lwp-dump File 2.65 KB 0755
lwp-mirror File 2.36 KB 0755
lwp-request File 15.87 KB 0755
lzcat File 103.02 KB 0755
lzcmp File 7.41 KB 0755
lzdiff File 7.41 KB 0755
lzegrep File 10.17 KB 0755
lzfgrep File 10.17 KB 0755
lzgrep File 10.17 KB 0755
lzless File 2.33 KB 0755
lzma File 103.02 KB 0755
lzmainfo File 14.45 KB 0755
lzmore File 2.18 KB 0755
m17n-db File 3.65 KB 0755
m2300w File 28.83 KB 0755
m2300w-wrapper File 14.24 KB 0755
m2400w File 32.83 KB 0755
make File 344.14 KB 0755
make-first-existing-target File 4.79 KB 0755
makedumpfile File 415.41 KB 0755
makedumpfile-R.pl File 4.83 KB 0755
mako-render File 972 B 0755
man File 129.48 KB 0755
man-recode File 35.48 KB 0755
mandb File 155.74 KB 0755
manpath File 26.86 KB 0755
mapscrn File 34.54 KB 0755
markdown-it File 220 B 0755
mawk File 190.84 KB 0755
mbim-network File 11.08 KB 0755
mbimcli File 216.82 KB 0755
mcookie File 26.52 KB 0755
md5sum File 42.49 KB 0755
md5sum.textutils File 42.49 KB 0755
mdig File 54.48 KB 0755
memhog File 14.42 KB 0755
mesa-overlay-control.py File 5.59 KB 0755
migrate-pubring-from-classic-gpg File 3.02 KB 0755
migratepages File 14.38 KB 0755
migspeed File 14.3 KB 0755
mimeopen File 9.41 KB 0755
mimetype File 12.76 KB 0755
min12xxw File 31.45 KB 0755
mk_modmap File 15.78 KB 0755
mkdir File 70.59 KB 0755
mkfifo File 42.59 KB 0755
mkfontdir File 65 B 0755
mkfontscale File 42.9 KB 0755
mknod File 46.59 KB 0755
mksquashfs File 286.95 KB 0755
mktemp File 38.59 KB 0755
mmcli File 278.02 KB 0755
modutil File 94.49 KB 0755
mokutil File 59.48 KB 0755
monitor-sensor File 18.38 KB 0755
more File 46.46 KB 0755
mount File 50.45 KB 4755
mountpoint File 18.45 KB 0755
mousetweaks File 74.3 KB 0755
mpris-proxy File 94.67 KB 0755
mpstat File 50.55 KB 0755
mscompress File 14.3 KB 0755
msexpand File 14.3 KB 0755
mt File 75.09 KB 0755
mt-gnu File 75.09 KB 0755
mtr File 80.33 KB 0755
mtr-packet File 34.38 KB 0755
mv File 134.6 KB 0755
my_print_defaults File 179.59 KB 0755
myisam_ftdump File 6.36 MB 0755
myisamchk File 6.57 MB 0755
myisamlog File 6.39 MB 0755
myisampack File 6.42 MB 0755
mysql File 6.63 MB 0755
mysql_config_editor File 165.27 KB 0755
mysql_migrate_keyring File 6.53 MB 0755
mysql_secure_installation File 6.45 MB 0755
mysql_tzinfo_to_sql File 79.15 KB 0755
mysqladmin File 6.47 MB 0755
mysqlanalyze File 6.48 MB 0755
mysqlbinlog File 6.86 MB 0755
mysqlcheck File 6.48 MB 0755
mysqld_multi File 26.73 KB 0755
mysqld_safe File 28.45 KB 0755
mysqldump File 6.57 MB 0755
mysqldumpslow File 7.54 KB 0755
mysqlimport File 6.46 MB 0755
mysqloptimize File 6.48 MB 0755
mysqlrepair File 6.48 MB 0755
mysqlshow File 6.46 MB 0755
mysqlslap File 6.47 MB 0755
namei File 22.45 KB 0755
nano File 328.65 KB 0755
nautilus File 1.6 MB 0755
nautilus-autorun-software File 18.38 KB 0755
nautilus-sendto File 22.23 KB 0755
nawk File 190.84 KB 0755
nc File 42.71 KB 0755
nc.openbsd File 42.71 KB 0755
neqn File 913 B 0755
netaddr File 211 B 0755
netcat File 42.71 KB 0755
netstat File 166.68 KB 0755
networkctl File 130.59 KB 0755
networkd-dispatcher File 19.88 KB 0755
newgrp File 18.45 KB 4755
ngettext File 38.46 KB 0755
nhlt-dmic-info File 18.55 KB 0755
nice File 38.59 KB 0755
nisdomainname File 22.3 KB 0755
nl File 42.68 KB 0755
nm File 47.57 KB 0755
nm-connection-editor File 963.06 KB 0755
nm-online File 22.45 KB 0755
nmcli File 1.03 MB 0755
nmtui File 891.73 KB 0755
nmtui-connect File 891.73 KB 0755
nmtui-edit File 891.73 KB 0755
nmtui-hostname File 891.73 KB 0755
nohup File 38.49 KB 0755
notify-send File 26.31 KB 0755
nproc File 38.59 KB 0755
nroff File 5.58 KB 0755
nsenter File 30.71 KB 0755
nslookup File 118.98 KB 0755
nss-addbuiltin File 30.68 KB 0755
nss-dbtest File 22.47 KB 0755
nss-pp File 86.46 KB 0755
nstat File 30.45 KB 0755
nsupdate File 82.62 KB 0755
ntfs-3g File 175.09 KB 4755
ntfs-3g.probe File 14.45 KB 0755
ntfscat File 26.45 KB 0755
ntfscluster File 38.46 KB 0755
ntfscmp File 30.45 KB 0755
ntfsdecrypt File 42.46 KB 0755
ntfsfallocate File 26.46 KB 0755
ntfsfix File 34.46 KB 0755
ntfsinfo File 58.46 KB 0755
ntfsls File 27.53 KB 0755
ntfsmove File 30.46 KB 0755
ntfsrecover File 114.45 KB 0755
ntfssecaudit File 90.94 KB 0755
ntfstruncate File 26.38 KB 0755
ntfsusermap File 18.38 KB 0755
ntfswipe File 46.98 KB 0755
numactl File 35.23 KB 0755
numastat File 35.56 KB 0755
numfmt File 62.6 KB 0755
nvidia-detector File 270 B 0755
oakdecode File 18.33 KB 0755
obexctl File 110.46 KB 0755
objcopy File 166.7 KB 0755
objdump File 397.89 KB 0755
oclock File 23.41 KB 0755
ocspclnt File 70.46 KB 0755
od File 62.59 KB 0755
oem-getlogs File 8.3 KB 0755
on_ac_power File 2.45 KB 0755
oomctl File 18.45 KB 0755
open File 31.53 KB 0755
openssl File 1.08 MB 0755
openvt File 22.8 KB 0755
opldecode File 18.31 KB 0755
orca File 9.52 KB 0755
orca-dm-wrapper File 70 B 0755
os-prober File 4.42 KB 0755
osirrox File 14.15 KB 0755
p11-kit File 214.78 KB 0755
p7content File 22.39 KB 0755
p7env File 18.38 KB 0755
p7sign File 26.39 KB 0755
p7verify File 22.38 KB 0755
pager File 216.21 KB 0755
paper File 22.59 KB 0755
paperconf File 14.38 KB 0755
papers File 6.82 MB 0755
papers-previewer File 46.59 KB 0755
papers-thumbnailer File 18.46 KB 0755
partx File 62.46 KB 0755
passwd File 91.45 KB 4755
paste File 38.49 KB 0755
patch File 182.52 KB 0755
pathchk File 38.59 KB 0755
pcilmr File 50.45 KB 0755
pdb3 File 88.79 KB 0755
pdb3.13 File 88.79 KB 0755
pdf2ps File 909 B 0755
pdfattach File 22.46 KB 0755
pdfdetach File 30.57 KB 0755
pdffonts File 22.6 KB 0755
pdfimages File 42.6 KB 0755
pdfinfo File 74.58 KB 0755
pdfseparate File 22.46 KB 0755
pdfsig File 47.01 KB 0755
pdftocairo File 174.66 KB 0755
pdftohtml File 114.49 KB 0755
pdftoppm File 38.66 KB 0755
pdftops File 34.76 KB 0755
pdftotext File 58.6 KB 0755
pdfunite File 34.46 KB 0755
peekfd File 14.38 KB 0755
perf File 10.59 MB 0755
perl File 3.86 MB 0755
perl5.40-x86_64-linux-gnu File 14.38 KB 0755
perl5.40.1 File 3.86 MB 0755
perlbug File 44.52 KB 0755
perldoc File 125 B 0755
perli11ndoc File 58.17 KB 0755
perlivp File 10.61 KB 0755
perlthanks File 44.52 KB 0755
perror File 1.53 MB 0755
pf2afm File 498 B 0755
pfbtopfa File 516 B 0755
pgrep File 34.55 KB 0755
phar File 14.88 KB 0755
phar.default File 14.88 KB 0755
phar.phar File 14.88 KB 0755
phar.phar.default File 14.88 KB 0755
phar.phar8.4 File 14.88 KB 0755
phar8.4 File 14.88 KB 0755
phar8.4.phar File 14.88 KB 0755
php File 5.79 MB 0755
php.default File 5.79 MB 0755
php8.4 File 5.79 MB 0755
pic File 228.12 KB 0755
pico File 328.65 KB 0755
piconv File 8.16 KB 0755
pidof File 26.3 KB 0755
pidstat File 50.55 KB 0755
pidwait File 34.55 KB 0755
pinentry File 86.73 KB 0755
pinentry-curses File 70.72 KB 0755
pinentry-gnome3 File 86.73 KB 0755
pinentry-x11 File 86.73 KB 0755
ping File 155.74 KB 0755
ping4 File 155.74 KB 0755
ping6 File 155.74 KB 0755
pinky File 42.49 KB 0755
pipewire File 14.45 KB 0755
pipewire-aes67 File 14.45 KB 0755
pipewire-avb File 14.45 KB 0755
pipewire-pulse File 14.45 KB 0755
pk12util File 75.08 KB 0755
pk1sign File 22.52 KB 0755
pkaction File 18.45 KB 0755
pkcheck File 26.38 KB 0755
pkcon File 58.38 KB 0755
pkexec File 30.3 KB 4755
pkill File 34.55 KB 0755
pkmon File 22.38 KB 0755
pkttyagent File 22.45 KB 0755
pl2pm File 4.43 KB 0755
pldd File 22.52 KB 0755
plog File 146 B 0755
plymouth File 54.45 KB 0755
pmap File 38.48 KB 0755
pnm2ppa File 1.57 MB 0755
pod2html File 3.95 KB 0755
pod2man File 18.46 KB 0755
pod2text File 12.8 KB 0755
pod2usage File 4.01 KB 0755
podchecker File 3.64 KB 0755
poff File 2.77 KB 0755
pon File 1.33 KB 0755
powerprofilesctl File 10.49 KB 0755
ppdc File 118.55 KB 0755
ppdhtml File 82.55 KB 0755
ppdi File 106.55 KB 0755
ppdmerge File 18.45 KB 0755
ppdpo File 90.55 KB 0755
pphs File 404 B 0755
pr File 78.64 KB 0755
precat File 5.52 KB 0755
preconv File 62.55 KB 0755
preunzip File 5.52 KB 0755
prezip File 5.52 KB 0755
prezip-bin File 14.38 KB 0755
printafm File 395 B 0755
printenv File 34.46 KB 0755
printer-profile File 5.51 KB 0755
printf File 42.59 KB 0755
prlimit File 26.97 KB 0755
pro File 1003 B 0755
prove File 13.36 KB 0755
prtstat File 22.45 KB 0755
ps File 163.07 KB 0755
ps2ascii File 494 B 0755
ps2epsi File 1.27 KB 0755
ps2pdf File 272 B 0755
ps2pdf12 File 257 B 0755
ps2pdf13 File 257 B 0755
ps2pdf14 File 257 B 0755
ps2pdfwr File 1.05 KB 0755
ps2ps File 647 B 0755
ps2ps2 File 669 B 0755
ps2txt File 494 B 0755
psfaddtable File 26.45 KB 0755
psfgettable File 26.45 KB 0755
psfstriptable File 26.45 KB 0755
psfxtable File 26.45 KB 0755
psicc File 14.39 KB 0755
pslog File 14.38 KB 0755
pstree File 63.4 KB 0755
pstree.x11 File 63.4 KB 0755
ptar File 3.48 KB 0755
ptardiff File 2.58 KB 0755
ptargrep File 4.29 KB 0755
ptx File 58.62 KB 0755
pw-cat File 102.45 KB 0755
pw-cli File 154.56 KB 0755
pw-config File 22.45 KB 0755
pw-container File 22.45 KB 0755
pw-dot File 62.45 KB 0755
pw-dsdplay File 102.45 KB 0755
pw-dump File 114.54 KB 0755
pw-encplay File 102.45 KB 0755
pw-link File 34.45 KB 0755
pw-loopback File 26.45 KB 0755
pw-metadata File 14.45 KB 0755
pw-mididump File 34.45 KB 0755
pw-midiplay File 102.45 KB 0755
pw-midirecord File 102.45 KB 0755
pw-mon File 106.5 KB 0755
pw-play File 102.45 KB 0755
pw-profiler File 26.45 KB 0755
pw-record File 102.45 KB 0755
pw-reserve File 26.45 KB 0755
pw-top File 50.45 KB 0755
pwd File 38.59 KB 0755
pwdecrypt File 22.39 KB 0755
pwdx File 14.45 KB 0755
py3clean File 7.59 KB 0755
py3compile File 12.99 KB 0755
py3versions File 12.52 KB 0755
pybabel File 956 B 0755
pybabel-python3 File 956 B 0755
pydoc3 File 80 B 0755
pydoc3.13 File 80 B 0755
pygettext3 File 23.87 KB 0755
pygettext3.13 File 23.87 KB 0755
pygmentize File 215 B 0755
pyserial-miniterm File 975 B 0755
pyserial-ports File 969 B 0755
python3 File 6.51 MB 0755
python3.13 File 6.51 MB 0755
pzstd File 866.54 KB 0755
qmi-firmware-update File 180.16 KB 0755
qmi-network File 16.04 KB 0755
qmicli File 647.17 KB 0755
qpdldecode File 22.6 KB 0755
quirks-handler File 2.4 KB 0755
ranlib File 54.56 KB 0755
rbash File 1.66 MB 0755
rctest File 42.4 KB 0755
rdma File 126.6 KB 0755
readelf File 790.98 KB 0755
readlink File 42.49 KB 0755
realpath File 42.49 KB 0755
red File 89 B 0755
remmina File 969.16 KB 0755
remmina-file-wrapper File 1.3 KB 0755
remmina-gnome File 530 B 0755
rename.ul File 22.45 KB 0755
rendercheck File 59.78 KB 0755
renice File 14.45 KB 0755
reset File 30.38 KB 0755
resizecons File 30.54 KB 0755
resizepart File 22.45 KB 0755
resolvectl File 178.69 KB 0755
rev File 14.45 KB 0755
rfcomm File 30.81 KB 0755
rgrep File 30 B 0755
rhythmbox File 14.38 KB 0755
rhythmbox-client File 56.29 KB 0755
rm File 62.59 KB 0755
rmdir File 38.49 KB 0755
rnano File 328.65 KB 0755
rotatelogs File 26.46 KB 0755
routel File 1.62 KB 0755
rpcgen File 94.59 KB 0755
rrsync File 12.7 KB 0755
rsaperf File 688.82 KB 0755
rstart File 2.55 KB 0755
rstartd File 1.43 KB 0755
rsync File 594.21 KB 0755
rsync-ssl File 5.01 KB 0755
rtla File 1.58 KB 0755
rtstat File 22.73 KB 0755
run-parts File 30.89 KB 0755
run-with-aspell File 57 B 0755
run0 File 82.9 KB 0755
runcon File 38.59 KB 0755
rview File 2.16 MB 0755
rygel File 50.45 KB 0755
sadf File 396.13 KB 0755
sane-find-scanner File 103.25 KB 0755
sar File 179.1 KB 0755
sar.sysstat File 179.1 KB 0755
savelog File 10.24 KB 0755
sbattach File 22.54 KB 0755
sbkeysync File 34.74 KB 0755
sbsiglist File 14.6 KB 0755
sbsign File 34.7 KB 0755
sbvarsign File 22.73 KB 0755
sbverify File 30.61 KB 0755
scanimage File 79.19 KB 0755
scp File 162.74 KB 0755
scp-dbus-service File 90 B 0755
screendump File 18.37 KB 0755
script File 54.45 KB 0755
scriptlive File 42.45 KB 0755
scriptreplay File 34.45 KB 0755
sdiff File 58.47 KB 0755
sdptool File 148.38 KB 0755
seahorse File 1.18 MB 0755
sed File 110.57 KB 0755
select-default-iwrap File 474 B 0755
select-editor File 2.62 KB 0755
selfserv File 74.42 KB 0755
sensible-browser File 1.06 KB 0755
sensible-editor File 1.51 KB 0755
sensible-pager File 824 B 0755
sensible-terminal File 1.08 KB 0755
seq File 42.59 KB 0755
session-migration File 22.15 KB 0755
sessreg File 14.38 KB 0755
setarch File 26.73 KB 0755
setfacl File 38.38 KB 0755
setfont File 54.91 KB 0755
setkeycodes File 14.45 KB 0755
setleds File 18.51 KB 0755
setlogcons File 14.45 KB 0755
setmetamode File 14.48 KB 0755
setpci File 34.46 KB 0755
setpriv File 46.46 KB 0755
setsid File 14.45 KB 0755
setterm File 38.45 KB 0755
setupcon File 40.01 KB 0755
setxkbmap File 30.78 KB 0755
sftp File 178.73 KB 0755
sg File 18.45 KB 4755
sh File 146.84 KB 0755
sha1sum File 42.49 KB 0755
sha224sum File 42.49 KB 0755
sha256sum File 42.49 KB 0755
sha384sum File 42.49 KB 0755
sha512sum File 42.49 KB 0755
shasum File 9.75 KB 0755
shlibsign File 38.76 KB 0755
shotwell File 5.92 MB 0755
showconsolefont File 18.45 KB 0755
showkey File 18.45 KB 0755
showrgb File 14.38 KB 0755
shred File 62.59 KB 0755
shuf File 50.59 KB 0755
signtool File 122.49 KB 0755
signver File 42.76 KB 0755
simple-scan File 522.44 KB 0755
size File 30.53 KB 0755
skill File 30.49 KB 0755
slabtop File 22.52 KB 0755
sleep File 34.59 KB 0755
slogin File 1.07 MB 0755
slxdecode File 18.31 KB 0755
smproxy File 26.39 KB 0755
snap File 18.41 MB 0755
snapctl File 7.1 MB 0755
snapfuse File 42.3 KB 0755
snapshot File 4.59 MB 0755
snice File 30.49 KB 0755
soelim File 38.55 KB 0755
soffice File 6.5 KB 0755
software-properties-gtk File 4.04 KB 0755
sort File 118.84 KB 0755
spa-acp-tool File 344.34 KB 0755
spa-inspect File 110.55 KB 0755
spa-json-dump File 34.45 KB 0755
spa-monitor File 14.55 KB 0755
spa-resample File 34.8 KB 0755
spd-conf File 1003 B 0755
spd-say File 31.21 KB 0755
spdsend File 14.38 KB 0755
speaker-test File 42.52 KB 0755
speech-dispatcher File 250.48 KB 0755
spice-vdagent File 82.85 KB 0755
splain File 19 KB 0755
split File 59.02 KB 0755
splitfont File 14.37 KB 0755
sqfscat File 147.9 KB 0755
sqfstar File 286.95 KB 0755
ss File 136.93 KB 0755
ssh File 1.07 MB 0755
ssh-add File 350.5 KB 0755
ssh-agent File 366.51 KB 2755
ssh-argv0 File 1.42 KB 0755
ssh-copy-id File 13.84 KB 0755
ssh-import-id File 985 B 0755
ssh-import-id-gh File 785 B 0755
ssh-import-id-lp File 785 B 0755
ssh-keygen File 526.52 KB 0755
ssh-keyscan File 538.52 KB 0755
ssltap File 78.46 KB 0755
sss_ssh_authorizedkeys File 34.38 KB 0755
sss_ssh_knownhosts File 34.38 KB 0755
sss_ssh_knownhostsproxy File 26.38 KB 0755
startx File 5.26 KB 0755
stat File 90.59 KB 0755
static-sh File 2.34 MB 0755
stdbuf File 38.59 KB 0755
strace File 2.13 MB 0755
strace-log-merge File 1.83 KB 0755
streamzip File 7.87 KB 0755
strings File 34.69 KB 0755
strip File 166.73 KB 0755
strsclnt File 46.41 KB 0755
stty File 66.6 KB 0755
su File 54.45 KB 4755
sudo File 287.48 KB 4755
sudoedit File 287.48 KB 4755
sudoreplay File 96.03 KB 0755
sum File 38.49 KB 0755
switcherooctl File 4.77 KB 0755
symkeyutil File 39.29 KB 0755
sync File 34.49 KB 0755
sysprof File 1.2 MB 0755
sysprof-agent File 474.84 KB 0755
sysprof-cat File 322.59 KB 0755
sysprof-cli File 474.84 KB 0755
systemctl File 299 KB 0755
systemd-ac-power File 14.45 KB 0755
systemd-analyze File 218.87 KB 0755
systemd-ask-password File 18.59 KB 0755
systemd-cat File 18.45 KB 0755
systemd-cgls File 22.57 KB 0755
systemd-cgtop File 38.47 KB 0755
systemd-confext File 74.65 KB 0755
systemd-creds File 50.74 KB 0755
systemd-cryptenroll File 83 KB 0755
systemd-cryptsetup File 79.05 KB 0755
systemd-delta File 26.45 KB 0755
systemd-detect-virt File 18.45 KB 0755
systemd-escape File 22.45 KB 0755
systemd-firstboot File 58.88 KB 0755
systemd-hwdb File 14.44 KB 0755
systemd-id128 File 26.45 KB 0755
systemd-inhibit File 22.47 KB 0755
systemd-machine-id-setup File 18.63 KB 0755
systemd-mount File 54.79 KB 0755
systemd-notify File 30.73 KB 0755
systemd-path File 18.45 KB 0755
systemd-run File 82.9 KB 0755
systemd-socket-activate File 30.45 KB 0755
systemd-stdio-bridge File 22.45 KB 0755
systemd-sysext File 74.65 KB 0755
systemd-sysusers File 66.63 KB 0755
systemd-tmpfiles File 126.7 KB 0755
systemd-tty-ask-password-agent File 34.45 KB 0755
systemd-umount File 54.79 KB 0755
systemd-vpick File 26.64 KB 0755
tabs File 18.38 KB 0755
tac File 42.49 KB 0755
tail File 74.61 KB 0755
tapestat File 30.55 KB 0755
tar File 510.04 KB 0755
taskset File 30.45 KB 0755
tbl File 154.55 KB 0755
tclsh File 14.23 KB 0755
tclsh8.6 File 14.23 KB 0755
tcpdump File 1.21 MB 0755
tecla File 66.52 KB 0755
tee File 42.59 KB 0755
telnet File 221.9 KB 0755
tempfile File 14.38 KB 0755
test File 34.51 KB 0755
thunderbird File 2.4 KB 0755
tic File 94.49 KB 0755
tificc File 34.46 KB 0755
time File 26.52 KB 0755
timedatectl File 46.45 KB 0755
timeout File 43.01 KB 0755
tinysparql File 60.69 KB 0755
tload File 22.47 KB 0755
tnftp File 182.9 KB 0755
toe File 22.38 KB 0755
top File 147.77 KB 0755
totem File 22.45 KB 0755
totem-video-thumbnailer File 38.48 KB 0755
touch File 82.59 KB 0755
tput File 26.41 KB 0755
tr File 50.55 KB 0755
trace-cmd File 435.41 KB 0755
tracepath File 18.23 KB 0755
transicc File 38.39 KB 0755
transmission-gtk File 2.78 MB 0755
transset File 22.78 KB 0755
troff File 818.7 KB 0755
true File 34.46 KB 0755
truncate File 38.59 KB 0755
trust File 246.78 KB 0755
tset File 30.38 KB 0755
tsort File 42.59 KB 0755
tstclnt File 106.5 KB 0755
tty File 34.59 KB 0755
turbostat File 1.58 KB 0755
tzselect File 21.39 KB 0755
ua File 1003 B 0755
ubuntu-advantage File 1003 B 0755
ubuntu-bug File 2.27 KB 0755
ubuntu-distro-info File 26.97 KB 0755
ubuntu-drivers File 18.25 KB 0755
ubuntu-report File 7.9 MB 0755
ubuntu-security-status File 22.25 KB 0755
ucf File 35.62 KB 0755
ucfq File 18.46 KB 0755
ucfr File 9.93 KB 0755
uclampset File 30.45 KB 0755
ucs2any File 26.38 KB 0755
udevadm File 618.84 KB 0755
udisksctl File 62.45 KB 0755
ul File 26.46 KB 0755
umax_pp File 191.53 KB 0755
umount File 38.45 KB 4755
uname File 34.59 KB 0755
unattended-upgrade File 116.54 KB 0755
unattended-upgrades File 116.54 KB 0755
uncompress File 2.28 KB 0755
unexpand File 38.61 KB 0755
unicode_start File 2.71 KB 0755
unicode_stop File 528 B 0755
uniq File 46.6 KB 0755
unity-scope-loader File 14.38 KB 0755
unlink File 34.59 KB 0755
unlzma File 103.02 KB 0755
unmkinitramfs File 6.23 KB 0755
unopkg File 52 B 0755
unshare File 46.68 KB 0755
unsquashfs File 147.9 KB 0755
unxz File 103.02 KB 0755
unzip File 190.61 KB 0755
unzipsfx File 94.63 KB 0755
unzstd File 1.22 MB 0755
update-alternatives File 66.46 KB 0755
update-desktop-database File 22.46 KB 0755
update-manager File 4.65 KB 0755
update-mime-database File 90.41 KB 0755
update-notifier File 91.23 KB 0755
upower File 18.38 KB 0755
uptime File 14.45 KB 0755
usb-creator-gtk File 2.87 KB 0755
usb-devices File 4.84 KB 0755
usb_printerid File 14.31 KB 0755
usbhid-dump File 30.46 KB 0755
usbip File 1.58 KB 0755
usbipd File 1.58 KB 0755
usbreset File 14.38 KB 0755
users File 38.59 KB 0755
uuidgen File 22.45 KB 0755
uuidparse File 22.45 KB 0755
varlinkctl File 38.57 KB 0755
vcs-run File 6.75 KB 0755
vdir File 155.02 KB 0755
vfychain File 74.47 KB 0755
vfyserv File 42.47 KB 0755
vi File 2.16 MB 0755
view File 2.16 MB 0755
viewres File 31.3 KB 0755
vim.tiny File 2.16 MB 0755
vmstat File 38.86 KB 0755
vmwarectrl File 14.26 KB 0755
vsftpdwho File 54 B 0755
vstp File 26.24 KB 0755
w File 26.45 KB 0755
wall File 26.45 KB 0755
watch File 34.92 KB 0755
watchgnupg File 22.38 KB 0755
wc File 62.59 KB 0755
wcurl File 10.3 KB 0755
wdctl File 34.48 KB 0755
wget File 579.05 KB 0755
whatis File 47.36 KB 0755
whereis File 30.91 KB 0755
which File 1.05 KB 0755
which.debianutils File 1.05 KB 0755
whiptail File 30.24 KB 0755
who File 46.6 KB 0755
whoami File 34.59 KB 0755
whoopsie File 50.98 KB 0755
whoopsie-preferences File 22.23 KB 0755
wireplumber File 18.64 KB 0755
word-list-compress File 14.38 KB 0755
wpa_passphrase File 14.46 KB 0755
wpctl File 62.51 KB 0755
wpexec File 18.63 KB 0755
wsdd File 72.92 KB 0755
x-session-manager File 958 B 0755
x-terminal-emulator File 6.06 KB 0755
x-www-browser File 2.32 KB 0755
x11perf File 197.46 KB 0755
x11perfcomp File 2.74 KB 0755
x86_64 File 26.73 KB 0755
x86_64-linux-gnu-addr2line File 30.78 KB 0755
x86_64-linux-gnu-ar File 54.56 KB 0755
x86_64-linux-gnu-as File 795.52 KB 0755
x86_64-linux-gnu-c++filt File 26.34 KB 0755
x86_64-linux-gnu-cpp File 1.13 MB 0755
x86_64-linux-gnu-cpp-14 File 1.13 MB 0755
x86_64-linux-gnu-elfedit File 34.79 KB 0755
x86_64-linux-gnu-gcc File 1.13 MB 0755
x86_64-linux-gnu-gcc-14 File 1.13 MB 0755
x86_64-linux-gnu-gcc-ar File 30.66 KB 0755
x86_64-linux-gnu-gcc-ar-14 File 30.66 KB 0755
x86_64-linux-gnu-gcc-nm File 30.66 KB 0755
x86_64-linux-gnu-gcc-nm-14 File 30.66 KB 0755
x86_64-linux-gnu-gcc-ranlib File 30.66 KB 0755
x86_64-linux-gnu-gcc-ranlib-14 File 30.66 KB 0755
x86_64-linux-gnu-gcov File 468.19 KB 0755
x86_64-linux-gnu-gcov-14 File 468.19 KB 0755
x86_64-linux-gnu-gcov-dump File 380.14 KB 0755
x86_64-linux-gnu-gcov-dump-14 File 380.14 KB 0755
x86_64-linux-gnu-gcov-tool File 408.23 KB 0755
x86_64-linux-gnu-gcov-tool-14 File 408.23 KB 0755
x86_64-linux-gnu-gprof File 99.86 KB 0755
x86_64-linux-gnu-ld File 1.78 MB 0755
x86_64-linux-gnu-ld.bfd File 1.78 MB 0755
x86_64-linux-gnu-lto-dump File 31.61 MB 0755
x86_64-linux-gnu-lto-dump-14 File 31.61 MB 0755
x86_64-linux-gnu-nm File 47.57 KB 0755
x86_64-linux-gnu-objcopy File 166.7 KB 0755
x86_64-linux-gnu-objdump File 397.89 KB 0755
x86_64-linux-gnu-ranlib File 54.56 KB 0755
x86_64-linux-gnu-readelf File 790.98 KB 0755
x86_64-linux-gnu-size File 30.53 KB 0755
x86_64-linux-gnu-strings File 34.69 KB 0755
x86_64-linux-gnu-strip File 166.73 KB 0755
x86_energy_perf_policy File 1.58 KB 0755
xargs File 66.49 KB 0755
xauth File 55.03 KB 0755
xbiff File 24.16 KB 0755
xbrlapi File 238.57 KB 0755
xcalc File 51.48 KB 0755
xclipboard File 22.58 KB 0755
xclock File 53.06 KB 0755
xcmsdb File 42.46 KB 0755
xconsole File 23.2 KB 0755
xcursorgen File 22.3 KB 0755
xcutsel File 18.56 KB 0755
xdg-dbus-proxy File 58.3 KB 0755
xdg-desktop-icon File 22.29 KB 0755
xdg-desktop-menu File 43.17 KB 0755
xdg-email File 28.24 KB 0755
xdg-icon-resource File 31.47 KB 0755
xdg-mime File 46.62 KB 0755
xdg-open File 31.53 KB 0755
xdg-screensaver File 38.55 KB 0755
xdg-settings File 43.31 KB 0755
xdg-terminal-exec File 33.69 KB 0755
xdg-user-dir File 234 B 0755
xdg-user-dirs-gtk-update File 22.3 KB 0755
xdg-user-dirs-update File 26.3 KB 0755
xditview File 108.13 KB 0755
xdpyinfo File 39.13 KB 0755
xdriinfo File 14.38 KB 0755
xedit File 705.34 KB 0755
xev File 34.7 KB 0755
xeyes File 32.13 KB 0755
xfd File 40.08 KB 0755
xfontsel File 47.92 KB 0755
xgamma File 14.38 KB 0755
xgc File 70.38 KB 0755
xhost File 22.38 KB 0755
xinit File 22.38 KB 0755
xinput File 58.83 KB 0755
xkbbell File 14.39 KB 0755
xkbcomp File 212.18 KB 0755
xkbevd File 38.46 KB 0755
xkbprint File 94.42 KB 0755
xkbvleds File 23.18 KB 0755
xkbwatch File 23.24 KB 0755
xkeystone File 16.58 KB 0755
xkill File 14.38 KB 0755
xload File 22.92 KB 0755
xlogo File 23.19 KB 0755
xlsatoms File 14.38 KB 0755
xlsclients File 18.38 KB 0755
xlsfonts File 26.48 KB 0755
xmag File 44.31 KB 0755
xman File 77.2 KB 0755
xmessage File 23.27 KB 0755
xmodmap File 46.75 KB 0755
xmore File 14.53 KB 0755
xorrecord File 14.15 KB 0755
xorriso File 14.15 KB 0755
xorrisofs File 14.15 KB 0755
xprop File 48.68 KB 0755
xqxdecode File 18.31 KB 0755
xrandr File 70.48 KB 0755
xrdb File 42.48 KB 0755
xrefresh File 14.46 KB 0755
xset File 34.38 KB 0755
xsetmode File 14.38 KB 0755
xsetpointer File 14.38 KB 0755
xsetroot File 18.38 KB 0755
xsetwacom File 59.84 KB 0755
xsm File 98.71 KB 0755
xstdcmap File 18.96 KB 0755
xsubpp File 5.05 KB 0755
xvidtune File 43.84 KB 0755
xvinfo File 18.38 KB 0755
xwd File 30.31 KB 0755
xwininfo File 50.46 KB 0755
xwud File 30.3 KB 0755
xxd File 22.36 KB 0755
xz File 103.02 KB 0755
xzcat File 103.02 KB 0755
xzcmp File 7.41 KB 0755
xzdiff File 7.41 KB 0755
xzegrep File 10.17 KB 0755
xzfgrep File 10.17 KB 0755
xzgrep File 10.17 KB 0755
xzless File 2.33 KB 0755
xzmore File 2.18 KB 0755
yelp File 58.3 KB 0755
yes File 34.46 KB 0755
ypdomainname File 22.3 KB 0755
zcat File 1.93 KB 0755
zcmp File 1.64 KB 0755
zdiff File 6.3 KB 0755
zdump File 30.36 KB 0755
zegrep File 29 B 0755
zenity File 148.94 KB 0755
zfgrep File 29 B 0755
zforce File 2.03 KB 0755
zgrep File 8.01 KB 0755
zip File 223.08 KB 0755
zipcloak File 74.48 KB 0755
zipdetails File 231.06 KB 0755
zipgrep File 2.89 KB 0755
zipinfo File 190.61 KB 0755
zipnote File 66.48 KB 0755
zipsplit File 62.48 KB 0755
zjsdecode File 26.32 KB 0755
zless File 2.38 KB 0755
zmore File 1.79 KB 0755
znew File 4.46 KB 0755
zstd File 1.22 MB 0755
zstdcat File 1.22 MB 0755
zstdgrep File 3.78 KB 0755
zstdless File 197 B 0755
zstdmt File 1.22 MB 0755
Filemanager