// Copyright 2013 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.netstack;

using fuchsia.net;
using fuchsia.net.dhcp;
using fuchsia.hardware.ethernet;
using zx;

enum Protocol {
    UNSPECIFIED = 0;
    UDP = 1;
    TCP = 2;
};

enum Status {
    OK = 0;
    UNKNOWN_ERROR = 1;
    DNS_ERROR = 2;
    PARSE_ERROR = 3;
    IPV4_ONLY = 4;
    UNKNOWN_INTERFACE = 5;
};

struct NetErr {
    Status status;
    string message;
};

struct InterfaceConfig {
    string name;

    /// An unstable file path corresponding to the interface. Used in watching the creation
    /// and destruction of the interface, or in accessing the interface using netdump.
    string filepath;

    uint32 metric;
    /// Deprecated; to configure a network interface, use SetDhcpClientStatus
    /// and SetInterfaceAddress instead.
    IpAddressConfig ip_address_config;
};

union IpAddressConfig {
    1: fuchsia.net.Subnet static_ip;
    2: bool dhcp;
};

/// https://linux.die.net/man/7/netdevice
struct NetInterface {
    uint32 id;
    uint32 flags;
    uint32 features;
    uint32 configuration;
    string name;
    /// addr is one of the interface's IPv4 addresses, even if the interface
    /// holds multiple. No guarantees are made about which address is used when
    /// an interface has multiple IPv4 addresses.
    ///
    /// If the interface does not have an IPv4 address, addr is the unspecified
    /// IPv4 address (0.0.0.0).
    fuchsia.net.IpAddress addr;
    /// netmask is addr's corresponding network mask.
    ///
    /// If the interface does not have an IPv4 address, netmask is the 0 netmask
    /// (0.0.0.0).
    fuchsia.net.IpAddress netmask;
    /// netmask is addr's corresponding network's broadcast address.
    ///
    /// If the interface does not have an IPv4 address, broadaddr is the
    /// unspecified IPv4 address (0.0.0.0).
    fuchsia.net.IpAddress broadaddr;
    vector<fuchsia.net.Subnet> ipv6addrs;
    bytes hwaddr;
};

/// New version that includes a metric value.
// TODO(NET-2078): Move this to NetInterface once Chromium stops using
// netstack.fidl.
struct NetInterface2 {
    uint32 id;
    uint32 flags;
    uint32 features;
    uint32 configuration;
    uint32 metric;
    string name;
    /// addr is one of the interface's IPv4 addresses, even if the interface
    /// holds multiple. No guarantees are made about which address is used when
    /// an interface has multiple IPv4 addresses.
    ///
    /// If the interface does not have an IPv4 address, addr is the unspecified
    /// IPv4 address (0.0.0.0).
    fuchsia.net.IpAddress addr;
    /// netmask is addr's corresponding network mask.
    ///
    /// If the interface does not have an IPv4 address, netmask is the 0 netmask
    /// (0.0.0.0).
    fuchsia.net.IpAddress netmask;
    /// netmask is addr's corresponding network's broadcast address.
    ///
    /// If the interface does not have an IPv4 address, broadaddr is the
    /// unspecified IPv4 address (0.0.0.0).
    fuchsia.net.IpAddress broadaddr;
    vector<fuchsia.net.Subnet> ipv6addrs;
    bytes hwaddr;
};

/// Flags for NetInterface.flags.
const uint32 NetInterfaceFlagUp = 0x01; // Set if the interface is up.
const uint32 NetInterfaceFlagDhcp = 0x02; // Set if DHCP is enabled.

struct RouteTableEntry {
    fuchsia.net.IpAddress destination;
    fuchsia.net.IpAddress netmask;
    fuchsia.net.IpAddress gateway;
    uint32 nicid;
};

/// New version that includes a metric value.
// TODO(NET-2078): Move this to NetInterface once Chromium stops using
// netstack.fidl.
struct RouteTableEntry2 {
    fuchsia.net.IpAddress destination;
    fuchsia.net.IpAddress netmask;
    fuchsia.net.IpAddress? gateway;
    uint32 nicid;
    uint32 metric;
};

struct SocketAddress {
    fuchsia.net.IpAddress addr;
    uint16 port;
};

[Discoverable]
protocol Netstack {
    /// Returns the list of registered network interfaces.
    GetInterfaces() -> (vector<NetInterface> interfaces);
    GetInterfaces2() -> (vector<NetInterface2> interfaces);

    // DEPRECATED: see devicesettings.fidl
    // Returns the netstack's node name.
    // 5: GetNodeName() -> (string node_name);

    /// Returns current route table.
    GetRouteTable() -> (vector<RouteTableEntry> rt);
    GetRouteTable2() -> (vector<RouteTableEntry2> rt);

    /// Sets the status (up or down) for the interface with the given nicid.
    SetInterfaceStatus(uint32 nicid, bool enabled);

    /// Sets the address for the interface with the given nicid.
    /// Masks off addr.PrefixLen bits from addr.Addr to set the subnet.
    SetInterfaceAddress(uint32 nicid, fuchsia.net.IpAddress addr, uint8 prefixLen) -> (NetErr result);

    /// Removes the address for the interface with the given nicid.
    /// Masks off addr.PrefixLen bits from addr.Addr to set the subnet.
    RemoveInterfaceAddress(uint32 nicid, fuchsia.net.IpAddress addr, uint8 prefixLen) -> (NetErr result);

    /// Sets the route metric for the interface with the given nicid.
    SetInterfaceMetric(uint32 nicid, uint32 metric) -> (NetErr result);

    /// Creates a bridge and returns the newly created nicid or an
    /// error if the creation fails.
    BridgeInterfaces(vector<uint32> nicids) -> (NetErr result, uint32 nicid);

    AddEthernetDevice(string topological_path, InterfaceConfig interfaceConfig, fuchsia.hardware.ethernet.Device device) -> (uint32 nicid);

    // TODO(stijlist): re-home this protocol. GetDhcpClient should be a member
    // of the protocol that eventually owns network interface management
    // in general.
    GetDhcpClient(uint32 nicid, request<fuchsia.net.dhcp.Client> client) -> () error zx.status;

    /// Begin a route transaction for atomically getting and setting the route
    /// table.  Returns true if a transaction can be started.
    StartRouteTableTransaction(request<RouteTableTransaction> routeTableTransaction) -> (zx.status status);

    -> OnInterfacesChanged(vector<NetInterface> interfaces);
};

[Discoverable]
protocol RouteTableTransaction {
    AddRoute(RouteTableEntry2 r) -> (zx.status status);
    DelRoute(RouteTableEntry2 r) -> (zx.status status);
};
