// Copyright 2018 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.stack;

using fuchsia.hardware.ethernet;
using fuchsia.net.name;
using fuchsia.net;

/// A path to a device node.
alias device_path = string:255;

/// An entry in the forwarding table for the network stack.
///
/// Valid if at least one of [`device_id`] and [`next_hop`] is specified.
type ForwardingEntry = struct {
    /// The destination subnet this route can be used to send to.
    subnet fuchsia.net.Subnet;

    /// The opaque identifier of the device to which packets should be forwarded. The zero value is
    /// interpreted as unspecified. If unspecified, [`next_hop`] must be set, and will be used by
    /// the server to select an appropriate device.
    device_id fuchsia.net.interface_id;

    /// The IP address of the next hop. Used for link-layer address resolution, if present.
    next_hop fuchsia.net.IpAddress:optional;

    /// This entry's metric. The zero value is interpreted as unspecified.
    metric uint32;
};

type Error = strict enum {
    INTERNAL = 1;
    NOT_SUPPORTED = 2;
    INVALID_ARGS = 3;
    BAD_STATE = 4;
    TIME_OUT = 5;
    NOT_FOUND = 6;
    ALREADY_EXISTS = 7;
    IO = 8;
};

@discoverable
protocol Stack {
    /// Add an Ethernet interface to the network stack. On success, returns the
    /// identifier assigned by the stack for use in subsequent calls.
    AddEthernetInterface(resource struct {
        topological_path device_path;
        device client_end:fuchsia.hardware.ethernet.Device;
    }) -> (struct {
        id fuchsia.net.interface_id;
    }) error Error;

    /// Remove an Ethernet interface from the network stack.
    DelEthernetInterface(struct {
        id fuchsia.net.interface_id;
    }) -> (struct {}) error Error;

    /// Enable the interface. Packets may be processed by the stack after this
    /// call is processed.
    // TODO(https://fxbug.dev/95449): Remove this when N3 implements Control.
    @deprecated("Use fuchsia.net.interfaces.admin/Control.Enable")
    EnableInterfaceDeprecated(struct {
        id fuchsia.net.interface_id;
    }) -> (struct {}) error Error;

    /// Disable the interface. The stack will no longer process packets after
    /// this call.
    // TODO(https://fxbug.dev/95449): Remove this when N3 implements Control.
    @deprecated("Use fuchsia.net.interfaces.admin/Control.Disable")
    DisableInterfaceDeprecated(struct {
        id fuchsia.net.interface_id;
    }) -> (struct {}) error Error;

    /// Add an address to the interface. If the interface already has an address
    /// of a given type that does not allow duplicates, this method will return
    /// an error.
    // TODO(https://fxbug.dev/92767): Remove this when N3 implements Control.
    @deprecated("Use fuchsia.net.interfaces.admin/Control.AddAddress")
    AddInterfaceAddressDeprecated(struct {
        id fuchsia.net.interface_id;
        addr fuchsia.net.Subnet;
    }) -> (struct {}) error Error;

    /// Remove the address from the interface. If the address is not assigned to
    /// the interface, an error is returned.
    // TODO(https://fxbug.dev/92767): Remove this when N3 implements Control.
    @deprecated("Use fuchsia.net.interfaces.admin/Control.RemoveAddress")
    DelInterfaceAddressDeprecated(struct {
        id fuchsia.net.interface_id;
        addr fuchsia.net.Subnet;
    }) -> (struct {}) error Error;

    /// List all the entries in the forwarding table for the network stack.
    // TODO(https://fxbug.dev/38528): This is unbounded for now, until we change
    // the API to allow for pagination.
    GetForwardingTable() -> (struct {
        table vector<ForwardingEntry>:MAX;
    });

    /// Add a new entry to the forwarding table.
    ///
    /// If the table already contains an entry with the same subnet and
    /// destination, an already exists error is returned.
    AddForwardingEntry(struct {
        entry ForwardingEntry;
    }) -> (struct {}) error Error;

    /// Removes the forwarding entry. The entry must exactly match an entry in
    /// the forwarding table, with the exception of the metric value, which is
    /// ignored.
    DelForwardingEntry(struct {
        entry ForwardingEntry;
    }) -> (struct {}) error Error;

    /// Sets the IP forwarding state for an interface.
    // TODO(https://fxbug.dev/94475): Remove this.
    @deprecated("Use fuchsia.net.interfaces.admin/Control.SetConfiguration")
    SetInterfaceIpForwardingDeprecated(struct {
        id fuchsia.net.interface_id;
        ip_version fuchsia.net.IpVersion;
        enabled bool;
    }) -> (struct {}) error Error;

    /// Get a [`fuchsia.net.name/DnsServerWatcher`].
    GetDnsServerWatcher(resource struct {
        watcher server_end:fuchsia.net.name.DnsServerWatcher;
    });
};

@discoverable
protocol Log {
    /// Dynamically set packet logging.
    // TODO(fxbug.dev/42432): replace with optional packet captures in Inspect
    // output.
    SetLogPackets(struct {
        enabled bool;
    }) -> ();
};
