blob: 3411cf13b65d238bded0987b9a10948287922dee [file] [log] [blame]
// Copyright 2019 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.
/// The neighbor table helps decide where to send IP packets. It allows for the
/// translation between IP addresses and MAC addresses.
///
/// With current implementations, the neighbor table uses the ARP or NDP
/// protocol to dynamically discover new neighbor entries for IPv4 or IPv6
/// addresses, respectively.
///
/// This library enables inspection and manipulation of the neighbor table.
/// * See [`fuchsia.net.neighbor/View`] for viewing neighbor table entries.
/// * See [`fuchsia.net.neighbor/Controller`] for adding static neighbor table
/// entries, and removing entries.
///
/// # Important Concepts
///
/// [`Entry`] represents a neighboring device and is stored in the neighbor
/// table, which is also managed by the networking stack.
///
/// # Privacy Considerations
///
/// The Neighbor API deals with MAC addresses, which are device identifiers and
/// should not be exposed to most applications. There are separate protocols for
/// inspecting and modifying the neighbor table; this is done to protect
/// sensitive data.
///
/// # Security Considerations
///
/// The Neighbor API enables clients to view and manipulate the neighbor table,
/// which should both be privileged actions and granted only to trusted
/// applications. Additionally, not all clients will need both read and write
/// access. This has been addressed by splitting methods into two protocols:
/// Viewer for read methods and Controller for write methods.
///
/// This API is not concerned with throttling consumption of ARP or NDP
/// messages. If a DoS of ARP/NDP packets reaches this API, the damage had
/// already been done. Once the packets reach the control plane, they are
/// processed by the networking stack where the DoS would first manifest.
library fuchsia.net.neighbor;
using fuchsia.net;
using zx;
/// Returns entries and events from the neighbor table. Clients can open an
/// iterator using the [`fuchsia.net.neighbor/View.EntryIterator`] method.
///
/// An atomic snapshot of the neighbor table is queued for clients upon opening
/// an EntryIterator. This snapshot consists of `existing` entries followed by
/// an [`IdleEvent`]. No other types of events will be sent before an
/// [`IdleEvent`].
closed protocol EntryIterator {
/// Take items from the iterator. If no items are available, block until one
/// is; otherwise, return immediately with items queued since the last
/// invocation.
///
/// This does not guarantee that, when blocking, only one item will be
/// returned; implementations may debounce or batch events.
///
/// Clients should only have one call of this method at a time; a second
/// call to this method while a call is already pending will cause the
/// server end of the protocol to be closed.
///
/// - response `events` a list of events that occurred since the last
/// invocation of this method.
strict GetNext() -> (struct {
events vector<@generated_name("EntryIteratorItem") strict union {
/// An existing entry in the neighbor table. Does not indicate that
/// an event occurred.
1: existing Entry;
/// Empty event for indicating there are no more
/// [`EntryIteratorItem.existing`] items to yield.
2: idle @generated_name("IdleEvent") struct {};
/// Event indicating a new entry has been added to the neighbor
/// table.
3: added Entry;
/// Event indicating an entry has changed.
4: changed Entry;
/// Event indicating an entry has been removed from the neighbor
/// table.
5: removed Entry;
}>:MAX_ITEM_BATCH_SIZE;
});
};
/// The maximum number of [`EntryIteratorItem`] returned in a
/// [`EntryIterator.GetNext`] response.
//
// This has been calculated with the following function:
// MAX_EVENT_BATCH_SIZE = floor_pow2(
// (ZX_CHANNEL_MAX_MSG_BYTES - RESPONSE_BYTES) / MAX_EVENT_BYTES
// )
// where,
// ZX_CHANNEL_MAX_MSG_BYTES = 65536 bytes
// RESPONSE_BYTES = size of [`EntryIterator.GetNext`] response = 32 bytes
// MAX_ITEM_BYTES = max size of [`EntryIteratorItem`] = 208 bytes
//
// It's rounded down to the next power of two for aesthetics and decreased
// sensitivity to changes to the underlying data structures.
// This value will need to be recomputed if any of the above numbers change.
const MAX_ITEM_BATCH_SIZE uint64 = 256;
/// Inspect the neighbor table.
@discoverable
closed protocol View {
/// Open a connection to an [`EntryIterator`] for listing existing entries
/// and optionally watching for state changes.
///
/// + request `it` grants access to the [`EntryIterator`].
/// + request `options` specifies the behavior of the [`EntryIterator`].
strict OpenEntryIterator(resource struct {
it server_end:EntryIterator;
/// Options for modifying the behavior of an [`EntryIterator`].
options @generated_name("EntryIteratorOptions") table {};
});
};
// TODO(https://fxbug.dev/42085349): Define and use domain-specific error enum
// instead of zx.Status.
/// Modify the neighbor table.
@discoverable
closed protocol Controller {
/// Create a static entry. If a conflict is found, overwrite the existing
/// entry. Conflicts occur when two entries have the same interface
/// identifier and IP address.
///
/// + request `interface` identifier for the interface used for
/// communicating with the neighbor.
/// + request `neighbor` IP address of the neighbor.
/// + request `mac` MAC address of the neighbor.
/// * error `ZX_ERR_INVALID_ARGS` if `neighbor` is not a valid
/// neighbor address or `mac` is not a unicast MAC address.
/// * error `ZX_ERR_NOT_FOUND` if `interface` does not exist.
/// * error `ZX_ERR_NOT_SUPPORTED` if `interface` does not keep a neighbor
/// table (e.g. point-to-point links).
strict AddEntry(struct {
interface fuchsia.net.InterfaceId;
neighbor fuchsia.net.IpAddress;
mac fuchsia.net.MacAddress;
}) -> () error zx.Status;
/// Delete a dynamic or static entry.
///
/// + request `interface` identifier for the interface associated with the
/// entry to be deleted.
/// + request `neighbor` IP address of the entry to be deleted.
/// * error `ZX_ERR_INVALID_ARGS` if `neighbor` is not a valid neighbor
/// address.
/// * error `ZX_ERR_NOT_FOUND` if no entries match `interface` and
/// `neighbor`.
/// * error `ZX_ERR_NOT_SUPPORTED` if `interface` does not keep a neighbor
/// table (e.g. point-to-point links).
strict RemoveEntry(struct {
interface fuchsia.net.InterfaceId;
neighbor fuchsia.net.IpAddress;
}) -> () error zx.Status;
/// Delete all dynamic and static entries belonging to an interface.
///
/// + request `interface` identifier for the interface associated with the
/// entries to be deleted.
/// + request `ip_version` the IP version to clear entries from.
/// * error `ZX_ERR_NOT_FOUND` if `interface` does not exist.
/// * error `ZX_ERR_NOT_SUPPORTED` if `interface` does not keep a neighbor
/// table (e.g. point-to-point links).
strict ClearEntries(struct {
interface fuchsia.net.InterfaceId;
ip_version fuchsia.net.IpVersion;
}) -> () error zx.Status;
};