| // 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; |
| }; |
| }; |
| |
| /// Provides a method to create new clients. |
| @discoverable |
| 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. |
| NewClient(resource struct { |
| params @generated_name("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 empty (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. |
| /// |
| /// Required. Must be greater than 0. |
| 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; |
| }; |
| }; |
| }; |
| 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. |
| 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). |
| 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. |
| 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. |
| Shutdown() -> () error zx.status; |
| }; |
| |
| /// Provides IPv6 prefixes acquired via Prefix delegation. |
| @discoverable |
| 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. |
| 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. |
| 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. |
| 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. |
| -> OnExit(struct { |
| reason @generated_name("PrefixControlExitReason") 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/114132): 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; |
| }; |
| }); |
| }; |