blob: ccff1dd5dfbd61433a270eae8f8f292f22418d3f [file] [log] [blame]
// Copyright 2020 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.
library fuchsia.net.dhcpv6;
using fuchsia.net.interfaces.admin;
using fuchsia.net.name;
using fuchsia.net;
using zx;
/// Default port a DHCPv6 client should listen to according to
/// [RFC 8415, Section 7.2](https://tools.ietf.org/html/rfc8415#section-7.2).
const DEFAULT_CLIENT_PORT uint16 = 546;
type Empty = struct {};
/// An IPv6 prefix and its lifetimes.
type Prefix = struct {
/// The IPv6 prefix.
///
/// The host bits of the address must be all zeroes.
prefix fuchsia.net.Ipv6AddressWithPrefix;
/// The prefix lifetimes.
lifetimes struct {
/// The time after which the prefix will no longer be valid.
///
/// Its value must be greater than 0. A value of
/// `ZX_TIME_INFINITE` indicates that the prefix will always
/// be valid. If the value indicates a time in the past,
/// the prefix is invalid and should not be used.
///
/// As a `zx.Time`, the value has
/// [monotonic clock semantics][monotonic], which implies
/// that it has no meaning outside of the host on which it
/// was generated and no meaning across host restarts.
///
/// [monotonic]: https://fuchsia.dev/fuchsia-src/concepts/time/monotonic
valid_until zx.Time;
/// The time after which the prefix will no longer be preferred.
///
/// Its value must be greater than 0. A value of
/// `ZX_TIME_INFINITE` indicates that the prefix will always
/// be preferred. If the value indicates a time in the past,
/// the prefix should be considered deprecated. The value must not
/// refer to a time after [`valid_until`].
///
/// As a `zx.Time`, the value has
/// [monotonic clock semantics][monotonic],
/// which implies that it has no meaning outside of the host on
/// which it was generated and no meaning across host restarts.
///
/// [monotonic]: https://fuchsia.dev/fuchsia-src/concepts/time/monotonic
preferred_until zx.Time;
};
};
/// Parameters to start a new DHCPv6 client with.
type NewClientParams = table {
/// The ID of the interface the client will run on.
///
/// Required.
1: interface_id uint64;
/// The socket address to use when communicating with servers.
///
/// DHCPv6 servers listen for link-local multicasts, so not using a
/// link-local address here may cause interoperability issues.
///
/// Client creation will fail with `INVALID_ARGS` if:
///
/// * a multicast address is provided;
/// * or a link-local address is provided, and its zone index
/// doesn't match `interface_id` (Fuchsia has a 1:1 mapping from
/// zone index to interface ID).
///
/// Client creation will fail if it fails to bind a socket to this
/// address.
///
/// Required.
2: address fuchsia.net.Ipv6SocketAddress;
/// Configuration for starting the DHCPv6 client.
///
/// If the configuration requests both addresses and other
/// configuration parameters, all information is requested in the
/// same message exchange, running in stateful mode. If only
/// configuration parameters are requested (no addresses), the
/// client runs in stateless mode, as described in
/// [RFC 8415, Section 6.1](https://tools.ietf.org/html/rfc8415#section-6.1).
///
/// Client creation will fail if `config` is not requesting any
/// information (all fields are empty), or if it contains invalid
/// fields.
///
/// Required.
3: config @generated_name("ClientConfig") table {
/// Configuration for requesting configuration information.
///
/// If not set, interpreted as empty (no configuration
/// information will be requested).
1: information_config @generated_name("InformationConfig") table {
/// Request a list of available DNS servers
/// [RFC 3646](https://tools.ietf.org/html/rfc3646).
///
/// If not set, interpreted as false;
1: dns_servers bool;
};
/// Non-temporary address configuration.
///
/// Configures the client to negotiate non-temporary
/// addresses (IA_NA), as defined in
/// [RFC 8415, section 6.2](https://tools.ietf.org/html/rfc8415#section-6.2).
///
/// If not set, interpreted as a configuration with an address count
/// of 0 (non-temporary addresses will not be negotiated). If invalid,
/// client creation will fail and the pipelined channel will be closed.
2: non_temporary_address_config @generated_name("AddressConfig") table {
/// Number of addresses.
///
/// If the value is 0, the client will not negotiate
/// non-temporary addresses, i.e. its messages to the
/// server will not contain the IA_NA option.
///
/// Required.
1: address_count uint8;
/// Preferred addresses.
///
/// The addresses are used as hints by DHCPv6 servers,
/// but may be ignored.
///
/// The size of `preferred_addresses` must be less than
/// or equal to `address_count`, otherwise the
/// `AddressConfig` is invalid.
///
/// Optional field. If not set, or if
/// `preferred_addresses` is empty, no address hints are
/// provided.
2: preferred_addresses vector<fuchsia.net.Ipv6Address>:MAX;
};
/// Prefix delegation configuration.
///
/// Configures the client to negotiate a delegated prefix
/// (IA_PD), as defined in [RFC 8415, section 6.3][RFC 8415 6.3].
///
/// Optional. If not set, delegated prefixes will not be
/// requested. If invalid, client creation will fail and
/// the pipelined channel will be closed.
///
/// [RFC 8415 6.3]: https://datatracker.ietf.org/doc/html/rfc8415#section-6.3
3: prefix_delegation_config strict union {
/// Request a prefix of any length.
1: empty Empty;
/// Request a prefix of a specific length.
///
/// Must be in the range [1, 128]; otherwise client creation will fail.
2: prefix_length uint8;
/// Request a specific prefix.
///
/// The prefix length must be in the range [1, 128], and the host bits of
/// the address must be all zeroes; otherwise client creation will fail.
3: prefix fuchsia.net.Ipv6AddressWithPrefix;
};
};
};
/// Provides a method to create new clients.
@discoverable
closed protocol ClientProvider {
/// Provides a DHCPv6 client.
///
/// + request `params` the parameters to create the client with.
/// + request `request` grants control over the client. Closed with an
/// epitaph if the client cannot be created.
strict NewClient(resource struct {
params NewClientParams;
request server_end:Client;
});
};
/// Provides methods to watch for discovered network configurations.
///
/// This protocol encodes the underlying object's lifetime in both directions;
/// the underlying object is alive iff both ends of the protocol are open. That
/// is:
///
/// - Closing the client end causes the object to be destroyed.
/// - Observing a closure of the server end indicates the object no longer
/// exists.
closed protocol Client {
compose fuchsia.net.name.DnsServerWatcher;
/// Returns an address and its parameters.
///
/// Yields a value for every address acquired by the client.
///
/// It is invalid to call this method while a previous call is pending.
/// Doing so will cause the server end of the protocol to be closed.
///
/// - response `address` the assigned address.
/// - response `address_parameters` the parameters of the address.
/// - response `address_state_provider` provides address assignment state
/// and enables updating address properties; client end is closed if
/// the address becomes invalid (its valid lifetime expires and Renew
/// and Rebind fail).
strict WatchAddress() -> (resource struct {
address fuchsia.net.Subnet;
address_parameters fuchsia.net.interfaces.admin.AddressParameters;
address_state_provider server_end:fuchsia.net.interfaces.admin.AddressStateProvider;
});
/// Hanging get for prefix leases.
///
/// The first call to this method will return when there is at least
/// one lease to report (the first call is guaranteed to return with a
/// non-empty vector). Subsequent calls will return immediately if there
/// is a change to report, or block until a change occurs.
///
/// It is invalid to call this method while a previous call is pending.
/// Doing so will cause the server end of the protocol to be closed.
///
/// - response `prefixes` the assigned prefixes and their lifetimes.
strict WatchPrefixes() -> (struct {
/// Prefixes must be unique on [`Prefix.prefix`].
///
/// Prefixes with a `Prefix.prefix` value that did not appear in
/// a previous value returned via this method are new; conversely
/// prefixes previously present may have been removed, and usage
/// should stop immediately. The same prefix may appear with updated
/// lifetime values.
///
/// Note that any prefix's valid lifetime expiring will cause the
/// method to return with said prefix removed; but preferred lifetime
/// elapsing does not cause this method to return.
prefixes vector<Prefix>:MAX;
});
/// Gracefully tears down the underlying object.
///
/// Blocks until any held addresses are gracefully released, as described in
/// [RFC 8415, Section 18.2.7](https://tools.ietf.org/html/rfc8415#section-18.2.7).
///
/// The server end of the protocol is closed after this method returns.
///
/// * error a `zx.Status` if any of the addresses were not gracefully
/// released, e.g. the client times out waiting for Reply to Release,
/// or the interface is down and sending Release fails.
strict Shutdown() -> () error zx.Status;
};
/// Provides IPv6 prefixes acquired via Prefix delegation.
@discoverable
closed protocol PrefixProvider {
/// Acquire an IPv6 prefix via Prefix Delegation.
///
/// If this method is called with invalid parameters, a terminal event
/// containing a reason detailing why will be sent via
/// [`PrefixControl.OnExit`] and the server end of [`PrefixControl`]
/// will be closed.
///
/// + request `config` prefix acquisition configuration.
/// + request `prefix` provides control over prefix acquisition.
strict AcquirePrefix(resource struct {
config @generated_name("AcquirePrefixConfig") table {
/// Optional. If specified, PD will only be performed on the
/// interface identified. If absent, the interface(s) to perform PD
/// on will be chosen by the server.
1: interface_id fuchsia.net.InterfaceId;
/// The preferred prefix length.
///
/// Note that the server will make a best effort to return a prefix
/// of the preferred length, but may return a shorter one.
///
/// Optional; if absent, interpreted as no preference for prefix
/// length.
///
/// Must be in the range [0, 128].
2: preferred_prefix_len uint8;
};
prefix server_end:PrefixControl;
});
};
/// Provides control over prefix acquisition.
///
/// If the client end is closed, prefix acquisition will stop. This means that
/// a best effort will be made to release leases back to the server, and no
/// further attempt will be made to acquire any of the prefixes this protocol
/// was configured to acquire.
closed protocol PrefixControl {
/// Hanging get for the prefix and its lifetimes.
///
/// The first call to this method is guaranteed to return
/// [`PrefixEvent.assigned`], and will occur when there is a prefix
/// to report. Subsequent calls will return immediately if there is a
/// change to report, or block until a change occurs.
///
/// It is invalid to call this method while a previous call is pending.
/// Doing so will cause the server end of the protocol to be closed with
/// the terminal event [`PrefixControlExitReason.DOUBLE_WATCH`].
///
/// - response `event` an optional prefix.
strict WatchPrefix() -> (struct {
event @generated_name("PrefixEvent") strict union {
/// No prefix is assigned.
///
/// If a previously-assigned prefix was received, usage must stop
/// immediately.
1: unassigned Empty;
/// The assigned prefix and lifetimes.
///
/// May receive consecutive updates with an assigned prefix -
/// callers must use the latest prefix subnet and drop the
/// older prefix if the prefix is different. If the prefix is
/// the same, the lifetimes must be updated to what is held in
/// the latest update.
2: assigned Prefix;
};
});
/// Terminal event yielded by the server before the server end is closed.
///
/// - response `reason` the reason this prefix acquisition stopped.
strict -> OnExit(struct {
reason @generated_name("PrefixControlExitReason") flexible enum {
/// The interface identified is invalid for acquiring a prefix on.
INVALID_INTERFACE = 1;
/// The preferred prefix length is invalid.
INVALID_PREFIX_LENGTH = 2;
// TODO(https://fxbug.dev/42065403): Support multiple clients
// requesting prefixes.
/// An existing [`PrefixControl`] channel has already been
/// established to acquire a prefix.
ALREADY_ACQUIRING = 3;
/// The interface to acquire the prefix on was removed. Can only
/// be returned if a specific interface ID was named when
/// initializing the protocol.
INTERFACE_REMOVED = 4;
/// More than one concurrent call to a watch method was made.
DOUBLE_WATCH = 5;
/// Acquiring prefixes is not supported.
NOT_SUPPORTED = 6;
};
});
};