// 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.interfaces;
using fuchsia.net;
using zx;

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

type NetErr = struct {
    status Status;
    message string:MAX;
};

type InterfaceConfig = struct {
    name fuchsia.net.interfaces.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.
    filepath string:MAX;

    metric uint32;
};

type RouteTableEntry = struct {
    destination fuchsia.net.Subnet;
    gateway fuchsia.net.IpAddress:optional;
    nicid uint32;
    metric uint32;
};

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

@discoverable
protocol Netstack {
    /// Returns current route table.
    GetRouteTable() -> (struct {
        rt vector<RouteTableEntry>:MAX;
    });

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

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

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

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

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

    /// Adds a new interface backed by the given ethernet device.
    AddEthernetDevice(resource struct {
        topological_path string:MAX;
        interface_config InterfaceConfig;
        device client_end:fuchsia.hardware.ethernet.Device;
    }) -> (struct {
        nicid uint32;
    }) error zx.status;

    /// Connects to a DHCP client.
    ///
    /// + request `nicid` the interface on which the target client is running.
    /// + request `request` grants control over the client.
    // TODO(stijlist): re-home this protocol. GetDhcpClient should be a member
    // of the protocol that eventually owns network interface management
    // in general.
    GetDhcpClient(resource struct {
        nicid uint32;
        client server_end:fuchsia.net.dhcp.Client;
    }) -> (struct {}) error zx.status;

    /// Begin a route transaction to synchronize updates to the route table.
    ///
    /// Returns `ZX_OK` if a transaction can be started; `ZX_ERR_SHOULD_WAIT` if a transaction is
    /// currently in progress.
    StartRouteTableTransaction(resource struct {
        route_table_transaction server_end:RouteTableTransaction;
    }) -> (struct {
        status zx.status;
    });
};

@discoverable
protocol RouteTableTransaction {
    AddRoute(struct {
        r RouteTableEntry;
    }) -> (struct {
        status zx.status;
    });
    DelRoute(struct {
        r RouteTableEntry;
    }) -> (struct {
        status zx.status;
    });
};
