// 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.hardware.ethernet;
using fuchsia.net.dhcp;
using fuchsia.net;
using fuchsia.posix.socket;
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 {
    fuchsia.posix.socket.interface_name 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;
    fuchsia.posix.socket.interface_name 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;
    fuchsia.posix.socket.interface_name 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);

    /// 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);
};
