blob: 63b48894888013f7b2e296254e1fd95c5600b2c0 [file] [log] [blame]
// Copyright 2025 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/// Protocols and types for socket diagnostics.
@available(added=HEAD)
library fuchsia.net.sockets;
using fuchsia.net;
using fuchsia.net.tcp;
using fuchsia.net.udp;
using fuchsia.net.matchers;
/// The top-level socket matcher for use in diagnostics protocols.
type IpSocketMatcher = flexible union {
/// Matches only a specific IP version.
1: family fuchsia.net.IpVersion;
/// Matches the source address of the socket.
2: src_addr fuchsia.net.matchers.Address;
/// Matches the address of the socket.
3: dst_addr fuchsia.net.matchers.Address;
/// Matches transport-level information for the socket.
4: proto fuchsia.net.matchers.SocketTransportProtocol;
/// Matches the network interface the socket was bound to (e.g. using
/// `SetBindToDevice`).
///
/// NOTE: This means it never never matches sockets that haven't been bound
/// to a specific interface, even if packets from the socket are using it.
5: bound_interface fuchsia.net.matchers.Interface;
/// Matches the cookie of the socket.
6: cookie fuchsia.net.matchers.SocketCookie;
/// Matches one mark on the socket.
7: mark fuchsia.net.matchers.Mark;
};
/// The maximum number of `IpSocketMatcher`s that can be specified in a request.
///
/// The theoretical maximum imposed by the 64 KiB Zircon channel message limit
/// is 629 (64 bytes of fixed overhead and 104 bytes per `IpSocketMatcher`).
/// However, as a practical limit to avoid unreasonable numbers of matchers.
const MAX_IP_SOCKET_MATCHERS uint32 = 128;
/// Provides diagnostic information IP sockets.
@discoverable
closed protocol Diagnostics {
/// Populates an iterator over all IP sockets that match the provided
/// filters.
///
/// Unbound sockets are not returned.
strict IterateIp(resource struct {
/// The `IpIterator` for streaming sockets back to the caller.
s server_end:IpIterator;
/// The types of extended information to request. Information is
/// only returned for qualifying sockets. For example, the `TCP_INFO`
/// extension has no effect on returned UDP sockets.
extensions flexible bits {
/// Populates the `tcp_info` field on returned TCP sockets.
TCP_INFO = 0b1;
};
/// Filters to apply to all sockets on the system in Conjunctive Normal
/// Form. Only sockets matched by all filters are returned through the
/// `IpIterator` protocol.
///
/// For example, if you want to match all IPv4 TCP sockets with a local
/// port of 22, but not on loopback, you could use the following query:
///
/// [
/// {
/// family: Ipv4,
/// },
/// {
/// proto: tcp {
/// src_port: {
/// start: 22,
/// end: 22,
/// invert: false,
/// }
/// },
/// },
/// {
/// src_addr: {
/// range: {
/// start: "127.0.0.1"
/// end: "127.0.0.1"
/// },
/// invert: true
/// },
/// },
/// ]
matchers vector<IpSocketMatcher>:MAX_IP_SOCKET_MATCHERS;
}) -> () error flexible enum {};
};
/// The largest number of results that can be returned in one call to
/// `IpIterator.Next`.
///
/// This limit is calculated to fit the maximum number of items into a single
/// 64 KiB Zircon channel message. In the current FIDL wire format, the fixed
/// overhead of the `IpIterator.Next()` response is 40 bytes, and the worst-case
/// size of a single `IpSocketState` is 706 bytes, so we selected the maximum N
/// where 40 + N * 706 <= 65535.
const MAX_BATCH_SIZE uint32 = 92;
/// The state for each individual socket returned from `IpIterator.Next()`.
type IpSocketState = table {
/// The address family of the socket's addresses. This, `src_addr`, and
/// `dst_addr` are guaranteed to be the same address family.
///
/// Required.
1: family fuchsia.net.IpVersion;
/// The source address of the socket.
///
/// Required.
2: src_addr fuchsia.net.IpAddress;
/// The destination address of the socket.
///
/// Present if the socket is connected.
3: dst_addr fuchsia.net.IpAddress;
/// The cookie of the socket, which is unique during this boot. May be
/// used in subsequent requests in addition to the tuple to identify this
/// particular socket, even if the tuple is reused.
///
/// Required.
5: cookie uint64;
/// All of the marks on the socket.
///
/// Required.
6: marks fuchsia.net.Marks;
/// Transport protocol-level information about the socket.
///
/// Required.
7: transport @generated_name("IpSocketTransportState") flexible union {
1: tcp @generated_name("IpSocketTcpState") table {
/// The source port of the TCP socket.
///
/// Required.
1: src_port uint16;
/// The destination port of the TCP socket.
///
/// Present if the socket is connected.
2: dst_port uint16;
/// The current TCP state machine state of the socket.
///
/// Required.
3: state fuchsia.net.tcp.State;
/// Extended TCP state.
///
/// Present if the `TCP_INFO` extension is specified in the request.
4: tcp_info fuchsia.net.tcp.Info;
};
2: udp @generated_name("IpSocketUdpState") table {
/// The source port of the UDP socket.
///
/// Required.
1: src_port uint16;
/// The destination port of the UDP socket.
///
/// Present if the socket is connected.
2: dst_port uint16;
/// Pseudo-state machine state for the UDP socket.
///
/// Required.
3: state fuchsia.net.udp.State;
};
};
};
/// Provides sockets as a response to a call to `Diagnostics.IterateIp`.
open protocol IpIterator {
/// Call repeatedly to stream results for a previous request to
/// `Diagnostics.IterateIp`.
///
/// A caller must make sure to retrieve sockets in a timely manner, or the
/// connection may be closed with `TIMED_OUT`.
///
/// NOTE: The returned sockets do not provide a consistent snapshot of the
/// system. For example, you should never use the state of one socket to
/// infer what the state of another socket will be, since modifications
/// could have occurred in between results for each socket being
/// materialized.
strict Next() -> (struct {
sockets vector<IpSocketState>:MAX_BATCH_SIZE;
/// Whether there are more results available. the server immediately
/// closes its end of the channel after yielding a response with
/// `has_more = false`.
///
/// NOTE: It's possible for `has_more` to be true when `sockets` is
/// empty. Don't use the length of `sockets` as the signal of when there
/// are no more results.
has_more bool;
});
};
/// Provides control operations on sockets.
@discoverable
closed protocol Control {
/// Disconnect the socket matched by the provided matchers. See
/// `Diagnostics.IterateIp` for matcher semantics.
///
/// Disconnecting a socket depends on the transport protocol. In all cases,
/// all further operations on the socket will return `ECONNABORTED`:
///
/// - UDP: the behavior is equivalent to calling
/// `fuchsia.posix.socket/*.Disconnect`. Any destination port and address,
/// and bound device are removed.
/// - TCP LISTEN state: TCP moves to state CLOSE. All non-accepted sockets
/// are closed and an RST is sent to the peer.
/// - TCP all other states: The TCP connection is put in state CLOSE and an
/// RST is sent to the remote peer, if required.
///
/// If no filters are specified, or the provided filters match all sockets,
/// an error is returned and no action is taken.
strict DisconnectIp(table {
/// Sockets matching all filters will be disconnected (see above).
///
/// More information on the semantics of the matchers can be found in
/// [`fuchsia.net.sockets.IpSocketMatcher`].
///
/// Required.
1: filters vector<IpSocketMatcher>:MAX_IP_SOCKET_MATCHERS;
/// If present, sockets are only disconnected if there are this many
/// or fewer matching sockets.
2: max_sockets uint32;
}) -> (struct {
/// The number of disconnected sockets.
disconnected uint32;
}) error flexible enum {
/// A set of filters were specified that would disconnect all sockets.
/// This indicates a bug in the request.
UNCONSTRAINED_FILTERS = 1;
/// The maximum number of sockets in the request was exceeded.
MAXIMUM_SOCKETS_EXCEEDED = 2;
};
};