/*
 *
 *    Copyright (c) 2014-2017 Nest Labs, Inc.
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

/**
 *    @file
 *      This file implements the TunnelEndPoint abstraction APIs in the Inet
 *      Layer for creation and management of tunnel interfaces instantiated
 *      within either Linux Sockets or LwIP.
 *
 */

#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif

#include <InetLayer/TunEndPoint.h>
#include <InetLayer/InetLayer.h>

#include <string.h>
#include <stdio.h>

#include <Weave/Core/WeaveEncoding.h>
#include <Weave/Support/CodeUtils.h>

#include "arpa-inet-compatibility.h"

#if WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
#include <fuchsia/netstack/cpp/fidl.h>
#endif

namespace nl {
namespace Inet {

using Weave::System::PacketBuffer;

Weave::System::ObjectPool<TunEndPoint, INET_CONFIG_NUM_TUN_ENDPOINTS> TunEndPoint::sPool;

using namespace nl::Weave::Encoding;

#if WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN

constexpr uint32_t kDefaultMtu = 1500;
constexpr uint8_t kTunPortId = 0;

namespace {

fuchsia::net::tun::DevicePortConfig DefaultPortConfig() {
  fuchsia::net::tun::BasePortConfig base;
  base.set_id(kTunPortId);

  // Add both ipv4 and ipv6 for supported rx frame types.
  std::vector<fuchsia::hardware::network::FrameType> rxFrameTypes;
  rxFrameTypes.push_back(fuchsia::hardware::network::FrameType::IPV4);
  rxFrameTypes.push_back(fuchsia::hardware::network::FrameType::IPV6);
  base.set_rx_types(std::move(rxFrameTypes));

  // Configure default MTU
  base.set_mtu(kDefaultMtu);

  // Add both ipv4 and ipv6 for supported tx frame types.
  // FrameType specifies the type of frame(IPv4/IPv6), features specific to
  // the frametype and the supported flags. We set both to 0, as we don't
  // need any specific features or flags.
  std::vector<fuchsia::hardware::network::FrameTypeSupport> txFrameTypes;
  txFrameTypes.push_back(fuchsia::hardware::network::FrameTypeSupport{
      fuchsia::hardware::network::FrameType::IPV4, 0,
      static_cast<fuchsia::hardware::network::TxFlags>(0)});
  txFrameTypes.push_back(fuchsia::hardware::network::FrameTypeSupport{
      fuchsia::hardware::network::FrameType::IPV6, 0,
      static_cast<fuchsia::hardware::network::TxFlags>(0)});
  base.set_tx_types(std::move(txFrameTypes));

  fuchsia::net::tun::DevicePortConfig config;
  config.set_base(std::move(base));

  return config;
}

fuchsia::net::tun::DeviceConfig DefaultDeviceConfig() {
  fuchsia::net::tun::DeviceConfig config;
  config.set_blocking(false);
  return config;
}
} // namespace

// Creates a tun device.
INET_ERROR TunEndPoint::CreateTunDevice(void) {
  fidl::InterfaceHandle<fuchsia::net::tun::Control> tun;
  auto config = DefaultDeviceConfig();
  zx_status_t err;
  InetLayer::FuchsiaPlatformData *platformData = static_cast<InetLayer::FuchsiaPlatformData*>(Layer().GetPlatformData());
  if (platformData == NULL || platformData->ctx == NULL) {
    WeaveLogError(Inet, "PlatformData is NULL");
    return INET_ERROR_INCORRECT_STATE;
  }
  err = platformData->ctx->svc()->Connect(tun.NewRequest());
  if (err != ZX_OK) {
    WeaveLogError(Inet, "Connect to network tun failed:  %s", zx_status_get_string(err));
    return err;
  }
  mTunCtl = tun.BindSync();
  if (!mTunCtl.is_bound()) {
    WeaveLogError(Inet, "tunctl is not bound");
    return INET_ERROR_INTERFACE_INIT_FAILURE;
  }
  err = mTunCtl->CreateDevice(std::move(config), mTunDevice.NewRequest());
  if(err != ZX_OK) {
    WeaveLogError(Inet, "tunctl failed to create device: %s", zx_status_get_string(err));
    return INET_ERROR_INTERFACE_INIT_FAILURE;
  }
  err = mTunDevice->AddPort(DefaultPortConfig(), mTunPort.NewRequest());
  if(err != ZX_OK) {
    WeaveLogError(Inet, "tunctl failed to add device port: %s", zx_status_get_string(err));
    return INET_ERROR_INTERFACE_INIT_FAILURE;
  }
  return INET_NO_ERROR;
}

// Add the tun interface to netstack. If successful the tun interface shows up in "net if list".
INET_ERROR TunEndPoint::AddInterfaceToNetstack(const char *intfName) {
  zx_status_t err;

  InetLayer::FuchsiaPlatformData *platformData = static_cast<InetLayer::FuchsiaPlatformData*>(Layer().GetPlatformData());
  if (platformData == NULL || platformData->ctx == NULL) {
    WeaveLogError(Inet, "PlatformData is NULL");
    return INET_ERROR_BAD_ARGS;
  }
  err = platformData->ctx->svc()->Connect(mStackPtr.NewRequest());
  if (err != ZX_OK) {
    WeaveLogError(Inet, "connect to stack fidl failed");
    return err;
  }

  fuchsia::hardware::network::DeviceHandle device;
  err = mTunDevice->GetDevice(device.NewRequest());
  if (err != ZX_OK) {
      WeaveLogError(Inet, "get device failed: %s", zx_status_get_string(err));
      return err;
  }
  fuchsia::hardware::network::PortSyncPtr port;
  err = mTunPort->GetPort(port.NewRequest());
  if (err != ZX_OK) {
      WeaveLogError(Inet, "get port failed: %s", zx_status_get_string(err));
      return err;
  }
  fuchsia::hardware::network::PortInfo port_info;
  err = port->GetInfo(&port_info);
  if (err != ZX_OK) {
      WeaveLogError(Inet, "port GetInfo failed: %s", zx_status_get_string(err));
      return err;
  }
  if (!port_info.has_id()) {
      WeaveLogError(Inet, "missing port id");
      return ZX_ERR_INTERNAL;
  }
  const fuchsia::hardware::network::PortId& port_id = port_info.id();

  fuchsia::net::interfaces::admin::InstallerSyncPtr installer;
  err = platformData->ctx->svc()->Connect(installer.NewRequest());
  if (err != ZX_OK) {
      WeaveLogError(Inet, "connect to installer fidl failed");
      return err;
  }
  err = installer->InstallDevice(std::move(device), mDeviceControlPtr.NewRequest());
  if (err != ZX_OK) {
      WeaveLogError(Inet, "InstallDevice failed: %s", zx_status_get_string(err));
      return err;
  }
  fuchsia::net::interfaces::admin::Options options;
  options.set_name(intfName);
  err = mDeviceControlPtr->CreateInterface(port_id, mControlPtr.NewRequest(), std::move(options));
  if (err != ZX_OK) {
      WeaveLogError(Inet, "CreateInterface failed: %s", zx_status_get_string(err));
      return err;
  }

  err = mControlPtr->GetId(&mInterfaceId);
  if (err != ZX_OK) {
      WeaveLogError(Inet, "GetId failed: %s", zx_status_get_string(err));
      return err;
  }

  return INET_NO_ERROR;
}

INET_ERROR TunEndPoint::CreateHostDevice(const char *intfName) {
  return AddInterfaceToNetstack(intfName);
}

/* Read packets from TUN device in Linux */
zx_status_t TunEndPoint::GetSignalsEventPair(zx::eventpair &events)
{
  if (!mTunCtl.is_bound()) {
    WeaveLogError(Inet, "Can't read as mtunctl is not bound");
    return ZX_ERR_INTERNAL;
  }

  zx_status_t status = mTunDevice->GetSignals(&events);
  if (status != 0) {
    WeaveLogError(Inet, "Failed to get signals from Tun: %s", zx_status_get_string(status));
    return status;
  }

  return ZX_OK;
}
#endif //WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN

/**
 * Initialize the Tunnel EndPoint object.
 *
 * @note
 *  By convention, the \c Init method on \c EndPointBasis
 *  subclasses is \c private. It should not be used outside \c InetLayer.
 *
 * @param[in] inetLayer       A pointer to the Inet layer object that
 *                            created the Tunnel EndPoint.
 *
 */
void TunEndPoint::Init(InetLayer *inetLayer)
{
    InitEndPointBasis(*inetLayer);
}

/**
 * Open a tunnel pseudo interface and create a handle to it.
 *
 * @note
 *  This method has different signatures on LwIP systems and
 *  POSIX systems.  On LwIP, there is an argument for specifying the name
 *  of the tunnel interface.  On POSIX, the method has no arguments and the
 *  name of the tunnel device is implied.
 *
 * @return INET_NO_ERROR on success, else a corresponding INET mapped OS error.
 */
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
INET_ERROR TunEndPoint::Open (void)
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP

#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
INET_ERROR TunEndPoint::Open (const char *intfName)
#endif //WEAVE_SYSTEM_CONFIG_USE_SOCKETS
{
    INET_ERROR err = INET_NO_ERROR;

#if WEAVE_SYSTEM_CONFIG_USE_LWIP
    struct netif *tNetif = NULL;
    // Lock LwIP stack
    LOCK_TCPIP_CORE();

    tNetif = netif_add(&mTunNetIf, NULL, NULL, NULL, this, TunInterfaceNetifInit, tcpip_input);

    // UnLock LwIP stack
    UNLOCK_TCPIP_CORE();

    VerifyOrExit(tNetif != NULL, err = INET_ERROR_INTERFACE_INIT_FAILURE);

#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP

#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS

    //Create the tunnel device
    err = TunDevOpen(intfName);
    SuccessOrExit(err);

    WeaveLogProgress(Inet, "Opened tunnel device: %s", intfName);

#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS

    if (err == INET_NO_ERROR)
        mState = kState_Open;

exit:

    return err;
}

/**
 * Close the tunnel pseudo interface device.
 *
 */
void TunEndPoint::Close (void)
{
    if (mState != kState_Closed)
    {

        // For LwIP, we do not remove the netif as it would have
        // an impact on the interface iterator in Weave which
        // might lose reference to a particular netif index that
        // it might be holding on to.
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
#if WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
        if (mInterfaceId >= 0)
#else
        if (mSocket >= 0)
#endif // WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
        {
            Weave::System::Layer& lSystemLayer = SystemLayer();

            // Wake the thread calling select so that it recognizes the socket is closed.
            lSystemLayer.WakeSelect();
            TunDevClose();
        }

        // Clear any results from select() that indicate pending I/O for the socket.
        mPendingIO.Clear();

#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
        mState = kState_Closed;
    }
}

/**
 * Close the tunnel pseudo interface device and decrement the reference count
 * of the InetLayer object.
 *
 */
void TunEndPoint::Free()
{
    Close();

#if WEAVE_SYSTEM_CONFIG_USE_LWIP
    DeferredFree(kReleaseDeferralErrorTactic_Release);
#else // !WEAVE_SYSTEM_CONFIG_USE_LWIP
    Release();
#endif // !WEAVE_SYSTEM_CONFIG_USE_LWIP
}

/**
 * Send an IPv6 packet to the tun device to be sent out.
 *
 * @note
 *  This method performs a couple of minimal sanity checks on the packet to
 *  be sure it is IP version 6 then dispatches it for encapsulation in a
 *  Weave tunneling message.
 *
 * @param[in]   message     the IPv6 packet to send.
 *
 * @retval  INET_NO_ERROR   success: packet encapsulated and queued to send
 * @retval  INET_ERROR_NOT_SUPPORTED    packet not IP version 6
 * @retval  INET_ERROR_BAD_ARGS         \c message is a \c NULL pointer
 *
 */
INET_ERROR TunEndPoint::Send (PacketBuffer *msg)
{
    INET_ERROR ret = INET_NO_ERROR;

    ret = CheckV6Sanity(msg);

    if (ret == INET_NO_ERROR)
    {
        ret = TunDevSendMessage(msg);
    }

    return ret;
}

/**
 * Extract the activation state of the tunnel interface.
 *
 * @returns \c true if the tunnel interface is active,
 *          otherwise \c false.
 */
bool TunEndPoint::IsInterfaceUp (void) const
{
    bool ret = false;

#if WEAVE_SYSTEM_CONFIG_USE_LWIP
    // Lock LwIP stack
    LOCK_TCPIP_CORE();

    ret = netif_is_up(&mTunNetIf);

    // UnLock LwIP stack
    UNLOCK_TCPIP_CORE();

    ExitNow();
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP

#if WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
    // TODO(https://fxbug.dev/80064): Migrate away from stack.GetInterfaceInfo.
    // NOTE: This is the last use of mStackPtr (fuchsia.net.stack/Stack) in this
    // class.
    if (!mStackPtr.is_bound()) {
      WeaveLogError(Inet, "mControlPtr is not bound");
      ExitNow(ret = false);
    }
    else {
      zx_status_t err;
      fuchsia::net::stack::Stack_GetInterfaceInfo_Result result;
      err = mStackPtr->GetInterfaceInfo(mInterfaceId, &result);
      if (err != ZX_OK) {
        WeaveLogError(Inet, "GetInterfaceInfo failed: %s", zx_status_get_string(err));
        ExitNow(ret = false);
      }
      fuchsia::net::stack::Stack_GetInterfaceInfo_Response resp = std::move(result.response());
      if (resp.info.properties.administrative_status == fuchsia::net::stack::AdministrativeStatus::ENABLED &&
          resp.info.properties.physical_status == fuchsia::net::stack::PhysicalStatus::UP) {
        ExitNow(ret = true);
      }
    }
#elif WEAVE_SYSTEM_CONFIG_USE_SOCKETS
    int sockfd = INET_INVALID_SOCKET_FD;
    struct ::ifreq ifr;

    memset(&ifr, 0, sizeof(ifr));

    //Get interface
    if (TunGetInterface(mSocket, &ifr) < 0)
    {
        ExitNow();
    }

    sockfd = socket(AF_INET6, SOCK_DGRAM | NL_SOCK_CLOEXEC, IPPROTO_IP);
    if (sockfd < 0)
    {
        ExitNow();
    }

    //Get interface flags
    if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0)
    {
        ExitNow();
    }

    ret = ((ifr.ifr_flags & IFF_UP) == IFF_UP);

#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS

exit:
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS && !WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
    if (sockfd >= 0)
    {
        close(sockfd);
    }
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS

    return ret;
}

/**
 * Activate the tunnel interface.
 *
 * @retval  INET_NO_ERROR           success: tunnel interface is activated.
 * @retval  other                   another system or platform error
 */
INET_ERROR TunEndPoint::InterfaceUp (void)
{
    INET_ERROR err = INET_NO_ERROR;

#if WEAVE_SYSTEM_CONFIG_USE_LWIP
    // Lock LwIP stack
    LOCK_TCPIP_CORE();

    netif_set_up(&mTunNetIf);

    // UnLock LwIP stack
    UNLOCK_TCPIP_CORE();

    ExitNow();
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP

#if WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
    // Set tun device to online.
    fuchsia::net::interfaces::admin::Control_Enable_Result result;
    err = mTunPort->SetOnline(true);
    if (err != ZX_OK) {
      WeaveLogError(Inet, "InterfaceUp failed due to SetOnline error: %s", zx_status_get_string(err));
      ExitNow();
    }
    if (!mControlPtr.is_bound()) {
      ExitNow(err = ZX_ERR_BAD_STATE);
    }

    // Enable the tun interface.
    err = mControlPtr->Enable(&result);
    if (err != ZX_OK) {
        WeaveLogError(Inet, "InterfaceUp failed due to Enable FIDL error: %s", zx_status_get_string(err));
        ExitNow();
    }
    if (result.is_err()) {
        WeaveLogError(Inet, "InterfaceUp failed due to Enable error: %d", result.err());
        ExitNow(err = ZX_ERR_INTERNAL);
    }
#elif WEAVE_SYSTEM_CONFIG_USE_SOCKETS
    int sockfd = INET_INVALID_SOCKET_FD;
    struct ::ifreq ifr;

    memset(&ifr, 0, sizeof(ifr));

    //Get interface
    if (TunGetInterface(mSocket, &ifr) < 0)
    {
        ExitNow(err = Weave::System::MapErrorPOSIX(errno));
    }

    sockfd = socket(AF_INET6, SOCK_DGRAM | NL_SOCK_CLOEXEC, IPPROTO_IP);
    if (sockfd < 0)
    {
        ExitNow(err = Weave::System::MapErrorPOSIX(errno));
    }

    //Get interface flags
    if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0)
    {
        ExitNow(err = Weave::System::MapErrorPOSIX(errno));
    }

    //Set flag to activate interface
    ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
    if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0)
    {
        err = Weave::System::MapErrorPOSIX(errno);
    }

    //Set the MTU
    ifr.ifr_mtu = WEAVE_CONFIG_TUNNEL_INTERFACE_MTU;
    if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0)
    {
        ExitNow(err = Weave::System::MapErrorPOSIX(errno));
    }

#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS

exit:
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS && !WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
    if (sockfd >= 0)
    {
        close(sockfd);
    }
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS

    return err;
}

/**
 * @brief   Deactivate the tunnel interface.
 *
 * @retval  INET_NO_ERROR           success: tunnel interface is deactivated.
 * @retval  other                   another system or platform error
 */
INET_ERROR TunEndPoint::InterfaceDown (void)
{
    INET_ERROR err = INET_NO_ERROR;

#if WEAVE_SYSTEM_CONFIG_USE_LWIP
    // Lock LwIP stack
    LOCK_TCPIP_CORE();

    //Remove the link local address from the netif
    memset(&(mTunNetIf.ip6_addr[0]), 0, sizeof(ip6_addr_t));

    netif_set_down(&mTunNetIf);

    // UnLock LwIP stack
    UNLOCK_TCPIP_CORE();

    ExitNow();
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP

#if WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
    fuchsia::net::interfaces::admin::Control_Disable_Result result;
    if (!mControlPtr.is_bound()) {
      WeaveLogError(Inet, "InterfaceDown failed as mControlPtr is not bound");
      ExitNow(err = ZX_ERR_BAD_STATE);
    }
    // Set offline and disable the interface.
    err = mTunPort->SetOnline(false);
    if (err != ZX_OK) {
      WeaveLogError(Inet, "InterfaceDown failed due to SetOnline error: %s", zx_status_get_string(err));
      ExitNow();
    }

    err = mControlPtr->Disable(&result);
    if (err != ZX_OK) {
        WeaveLogError(Inet, "InterfaceDown failed due to Disable FIDL error: %s", zx_status_get_string(err));
        ExitNow();
    }
    if (result.is_err()) {
        WeaveLogError(Inet, "InterfaceDown failed due to Disable error: %d", result.err());
        ExitNow(err = ZX_ERR_INTERNAL);
    }

#elif WEAVE_SYSTEM_CONFIG_USE_SOCKETS
    int sockfd = INET_INVALID_SOCKET_FD;
    struct ::ifreq ifr;
    memset(&ifr, 0, sizeof(ifr));

    //Get interface
    if (TunGetInterface(mSocket, &ifr) < 0)
    {
        ExitNow(err = Weave::System::MapErrorPOSIX(errno));
    }

    sockfd = socket(AF_INET6, SOCK_DGRAM | NL_SOCK_CLOEXEC, IPPROTO_IP);
    if (sockfd < 0)
    {
        ExitNow(err = Weave::System::MapErrorPOSIX(errno));
    }

    //Get interface flags
    if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0)
    {
        ExitNow(err = Weave::System::MapErrorPOSIX(errno));
    }

    //Set flag to deactivate interface
    ifr.ifr_flags &= ~(IFF_UP);
    if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0)
    {
        err = Weave::System::MapErrorPOSIX(errno);
    }
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS

exit:
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS && !WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
    if (sockfd >= 0)
    {
        close(sockfd);
    }
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS

    return err;
}

/**
 * @brief   Get the tunnel interface identifier.
 *
 * @return  The tunnel interface identifier.
 */
InterfaceId TunEndPoint::GetTunnelInterfaceId(void)
{
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
    return &mTunNetIf;
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP

#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS && !WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
    INET_ERROR err = INET_NO_ERROR;
    InterfaceId tunIntfId = INET_NULL_INTERFACEID;
    const char *tunIntfPtr = &tunIntfName[0];

    err = InterfaceNameToId(tunIntfPtr, tunIntfId);
    if (err != INET_NO_ERROR)
    {
        tunIntfId = INET_NULL_INTERFACEID;
    }

    return tunIntfId;
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
#if WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
    return mInterfaceId;
#endif
}

#if WEAVE_SYSTEM_CONFIG_USE_LWIP
/* Function for sending the IPv6 packets over LwIP */
INET_ERROR TunEndPoint::TunDevSendMessage(PacketBuffer *msg)
{
    INET_ERROR ret = INET_NO_ERROR;
    struct pbuf *p = NULL;
    err_t  err = ERR_OK;

    // no packet could be read, silently ignore this
    VerifyOrExit(msg != NULL, ret = INET_ERROR_BAD_ARGS);

    p = (struct pbuf *)msg;

    //Call the input function for the netif object in LWIP.
    //This essentially creates a TCP_IP msg and puts into
    //the mbox message queue for processing by the TCP/IP
    //stack.

    if ((err = tcpip_input(p, &mTunNetIf)) != ERR_OK)
    {
        LWIP_DEBUGF(NETIF_DEBUG, ("tunNetif_input: IP input error"));
        ExitNow(ret = Weave::System::MapErrorLwIP(err));
    }

exit:
    return (ret);
}
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP

#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
/* Function for sending the IPv6 packets over Linux sockets */
INET_ERROR TunEndPoint::TunDevSendMessage(PacketBuffer *msg)
{
    INET_ERROR ret = INET_NO_ERROR;
    uint8_t *p = NULL;

#if WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
    fuchsia::net::tun::Frame frame;
    fuchsia::net::tun::Device_WriteFrame_Result result;
    if (msg == NULL) {
      return INET_ERROR_BAD_ARGS;
    }
    p = msg->Start();
    std::vector<uint8_t> data(p, p + msg->DataLength());
    if (!mTunCtl.is_bound()) {
      WeaveLogError(Inet, "send failed as tunctl is not bound");
      return ZX_ERR_BAD_STATE;
    }

    frame.set_port(kTunPortId);
    frame.set_frame_type(fuchsia::hardware::network::FrameType::IPV6);
    frame.set_data(data);
    ret = mTunDevice->WriteFrame(std::move(frame), &result);
    if (ret != ZX_OK) {
      WeaveLogError(Inet, "write failed: %s", zx_status_get_string(ret));
      return ret;
    }
    if (result.is_err()) {
      WeaveLogError(Inet, "write failed: %s", zx_status_get_string(result.err()));
      return result.err();
    }
#else
    ssize_t lenSent = 0;
    // no packet could be read, silently ignore this
    VerifyOrExit(msg != NULL, ret = INET_ERROR_BAD_ARGS);

    p = msg->Start();
    lenSent = write(mSocket, p, msg->DataLength());
    if (lenSent < 0)
    {
       ExitNow(ret = Weave::System::MapErrorPOSIX(errno));
    }
    else if (lenSent < msg->DataLength())
    {
        ExitNow(ret = INET_ERROR_OUTBOUND_MESSAGE_TRUNCATED);
    }
exit:
#endif
    if (msg != NULL)
    {
        PacketBuffer::Free(msg);
    }

    return (ret);
}
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS

/* Function that performs some basic sanity checks for IPv6 packets */
INET_ERROR TunEndPoint::CheckV6Sanity (PacketBuffer *msg)
{
    INET_ERROR err = INET_NO_ERROR;
    uint8_t *p     = NULL;
    struct ip6_hdr *ip6hdr = NULL;

    p = msg->Start();

    ip6hdr = (struct ip6_hdr *)p;

    VerifyOrExit(ip6hdr != NULL, err = INET_ERROR_BAD_ARGS);

    //Do some IPv6 sanity checks
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
    if (IP6H_V(ip6hdr) != 6)
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP

#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
    if ((ip6hdr->ip6_vfc >> 4) != 6)
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
    {
        ExitNow(err = INET_ERROR_NOT_SUPPORTED);
    }

exit:

    return err;
}

#if WEAVE_SYSTEM_CONFIG_USE_LWIP
/* Handler to send received packet to upper layer callback */
void TunEndPoint::HandleDataReceived (PacketBuffer *msg)
{
    INET_ERROR err = INET_NO_ERROR;
    if (mState == kState_Open && OnPacketReceived != NULL)
    {
        err = CheckV6Sanity(msg);
        if (err == INET_NO_ERROR)
        {
            OnPacketReceived(this, msg);
        }
        else
        {
            if (OnReceiveError != NULL)
            {
                OnReceiveError(this, err);
            }

            PacketBuffer::Free(msg);
        }
    }
    else
    {
        PacketBuffer::Free(msg);
    }
}

/* Post an event to the Inet layer event queue from LwIP */
err_t TunEndPoint::LwIPPostToInetEventQ (struct netif *netif, struct pbuf *p)
{
    err_t                   lwipErr         = ERR_OK;
    INET_ERROR              err             = INET_NO_ERROR;
    TunEndPoint*            ep              = static_cast<TunEndPoint *>(netif->state);
    Weave::System::Layer&   lSystemLayer    = ep->SystemLayer();

    // Allocate space for the tunneled IP packet. The reserved space will be the
    // default for the Weave and underlying TCP/IP headers (WEAVE_SYSTEM_CONFIG_HEADER_RESERVE_SIZE).
    // The requested data size will include the full pbuf received from LwIP plus
    // WEAVE_TRAILER_RESERVE_SIZE for holding the HMAC.
    PacketBuffer* buf = PacketBuffer::NewWithAvailableSize(p->tot_len + WEAVE_TRAILER_RESERVE_SIZE);
    VerifyOrExit(buf != NULL, lwipErr = ERR_MEM);

    buf->SetDataLength(p->tot_len);

    // Make a pbuf alloc and copy to post to Inetlayer queue because LwIP would free the
    // passed pbuf as it made a down-call to send it out the tunnel netif.

    lwipErr = pbuf_copy((struct pbuf *)buf, p);
    VerifyOrExit(lwipErr == ERR_OK, (void)lwipErr);

    err = lSystemLayer.PostEvent(*ep, kInetEvent_TunDataReceived, (uintptr_t)buf);
    VerifyOrExit(err == INET_NO_ERROR, lwipErr = ERR_MEM);

    buf = NULL;

exit:
    if (buf != NULL)
    {
        PacketBuffer::Free(buf);
    }

    return lwipErr;
}

#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5
#if LWIP_IPV4
/* Output handler for netif */
err_t TunEndPoint::LwIPOutputIPv4(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr)
{
    LWIP_UNUSED_ARG(addr);

    return LwIPPostToInetEventQ(netif, p);
}
#endif // LWIP_IPV4

#if LWIP_IPV6
/* Output handler for netif */
err_t TunEndPoint::LwIPOutputIPv6(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr)
{
    LWIP_UNUSED_ARG(addr);

    return LwIPPostToInetEventQ(netif, p);
}
#endif // LWIP_IPV4
#else // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR < 5
/* Receive message in LwIP */
err_t TunEndPoint::LwIPReceiveTunMessage (struct netif *netif, struct pbuf *p, ip4_addr_t *addr)
{
    LWIP_UNUSED_ARG(addr);

    return LwIPPostToInetEventQ(netif, p);
}

#if LWIP_IPV6
err_t TunEndPoint::LwIPReceiveTunV6Message (struct netif *netif, struct pbuf *p, ip6_addr_t *addr)
{
    LWIP_UNUSED_ARG(addr);

    return LwIPPostToInetEventQ(netif, p);
}
#endif // LWIP_IPV6
#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR < 5

/* Initialize the LwIP tunnel netif interface */
err_t TunEndPoint::TunInterfaceNetifInit (struct netif *netif)
{
    netif->name[0] = 't';
    netif->name[1] = 'n';
#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5
#if LWIP_IPV4
    netif->output = LwIPOutputIPv4;
#endif /* LWIP_IPV6 */
#if LWIP_IPV6
    netif->output_ip6 = LwIPOutputIPv6;
#endif /* LWIP_IPV6 */
#else // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR < 5
    netif->output = LwIPReceiveTunMessage;
#if LWIP_IPV6
    netif->output_ip6 = LwIPReceiveTunV6Message;
#endif /* LWIP_IPV6 */
#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR < 5
    netif->linkoutput = NULL;

    netif->mtu = WEAVE_CONFIG_TUNNEL_INTERFACE_MTU;

    netif->hwaddr_len = 6;
    memset(netif->hwaddr, 0, NETIF_MAX_HWADDR_LEN);
    netif->hwaddr[5] = 1;

#if LWIP_VERSION_MAJOR == 1 && LWIP_VERSION_MINOR < 5
    /* device capabilities */
    netif->flags |= NETIF_FLAG_POINTTOPOINT;
#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5

    return ERR_OK;
}

#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP

#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
/* Open a tun device in linux */
INET_ERROR TunEndPoint::TunDevOpen (const char *intfName)
{
#if WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
    INET_ERROR ret = INET_NO_ERROR;
    //Create the tunnel device
    ret = CreateTunDevice();
    if (ret != 0) {
      WeaveLogError(Inet, "CreateTunDevice failed %d", ret);
      return ret;
    }

    ret = CreateHostDevice(intfName);
    if (ret != 0) {
      WeaveLogError(Inet, "CreateHostDevice failed %d", ret);
      return ret;
    }
    return ret;
#else
    struct ::ifreq ifr;
    int fd = INET_INVALID_SOCKET_FD;
    INET_ERROR ret = INET_NO_ERROR;

    if ((fd = open(INET_CONFIG_TUNNEL_DEVICE_NAME, O_RDWR | NL_O_CLOEXEC)) < 0)
    {
        ExitNow(ret = Weave::System::MapErrorPOSIX(errno));
    }

    //Keep copy of open device fd
    mSocket = fd;

    memset(&ifr, 0, sizeof(ifr));

    ifr.ifr_flags = IFF_TUN | IFF_NO_PI;

    if (*intfName)
    {
        strncpy(ifr.ifr_name, intfName, sizeof(ifr.ifr_name) - 1);
    }

    if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0)
    {
        ExitNow(ret = Weave::System::MapErrorPOSIX(errno));
    }

    //Verify name
    memset(&ifr, 0, sizeof(ifr));
    if (TunGetInterface(fd, &ifr) < 0)
    {
        ExitNow(ret = Weave::System::MapErrorPOSIX(errno));
    }

    if (ifr.ifr_name[0] != '\0')
    {
        //Keep member copy of interface name and Id
        strncpy(tunIntfName, ifr.ifr_name, sizeof(tunIntfName) - 1);
        tunIntfName[sizeof(tunIntfName) - 1] = '\0';
    }
    else
    {
        ExitNow(ret = Weave::System::MapErrorPOSIX(errno));
    }

exit:

    if (ret != INET_NO_ERROR)
    {
        TunDevClose();
    }
    return ret;
#endif
}

/* Close a tun device */
void TunEndPoint::TunDevClose (void)
{
#if WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
  fuchsia::net::stack::Stack_DelEthernetInterface_Result result;
  if (!mControlPtr.is_bound()) {
    WeaveLogError(Inet, "TunDevClose failed as mControlPtr is not bound");
    return;
  }
  // Dropping the control handles will cause the interface to be removed.
  mControlPtr.Unbind();
  mDeviceControlPtr.Unbind();
  mInterfaceId = 0;
#else
    if (mSocket >= 0)
    {
        close(mSocket);
    }
    mSocket = INET_INVALID_SOCKET_FD;
#endif
}

#if !WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
/* Get the tun device interface in Linux */
int TunEndPoint::TunGetInterface (int fd,
                                  struct ::ifreq *ifr)
{
    return ioctl(fd, TUNGETIFF, (void*)ifr);
}
#endif // !WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN

INET_ERROR TunEndPoint::TunDevRead (PacketBuffer *msg)
{
    INET_ERROR err = INET_NO_ERROR;
    uint8_t *p = NULL;
    p = msg->Start();

#ifdef WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
    fuchsia::net::tun::Device_ReadFrame_Result result;
    if (!mTunCtl.is_bound()) {
      WeaveLogError(Inet, "Can't read as mTunCtl is not bound");
      ExitNow(err = ZX_ERR_BAD_STATE);
    }
    err = mTunDevice->ReadFrame(&result);
    if (result.is_err()) {
      ExitNow(err = result.err());
    }
    if (result.is_response()) {
      std::vector<uint8_t> data = result.response().frame.data();
      memcpy(p, data.data(), data.size());
      msg->SetDataLength((uint16_t)data.size());
    }
#else
    ssize_t rcvLen;
    rcvLen = read(mSocket, p, msg->AvailableDataLength());
    if (rcvLen < 0)
    {
        err = Weave::System::MapErrorPOSIX(errno);
    }
    else if (rcvLen > msg->AvailableDataLength())
    {
        err = INET_ERROR_INBOUND_MESSAGE_TOO_BIG;
    }
    else
    {
        msg->SetDataLength((uint16_t)rcvLen);
    }
#endif //WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
exit:
    return err;
}

/* Prepare socket for reading */
SocketEvents TunEndPoint::PrepareIO ()
{
    SocketEvents res;

    if (mState == kState_Open && OnPacketReceived != NULL)
    {
        res.SetRead();
    }

    return res;
}

/* Read from the Tun device in Linux and pass up to upper layer callback */
void TunEndPoint::HandlePendingIO ()
{
    INET_ERROR err = INET_NO_ERROR;

    if (mState == kState_Open && OnPacketReceived != NULL && mPendingIO.IsReadable())
    {

        PacketBuffer *buf = PacketBuffer::New(0);

        if (buf != NULL)
        {
            //Read data from Tun Device
            err = TunDevRead(buf);
            if (err == INET_NO_ERROR)
            {
                err = CheckV6Sanity(buf);
            }
        }
        else
        {
            err = INET_ERROR_NO_MEMORY;
        }

        if (err == INET_NO_ERROR)
        {
            OnPacketReceived(this, buf);
        }
        else
        {
            PacketBuffer::Free(buf);
            if (OnReceiveError != NULL)
            {
                OnReceiveError(this, err);
            }
        }
    }

    mPendingIO.Clear();
}

#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS

} // namespace Inet
} // namespace nl
