/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * 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.
 */
#include "common/libs/net/netlink_client.h"

#include <errno.h>
#include <linux/rtnetlink.h>
#include <linux/sockios.h>
#include <net/if.h>
#include <sys/socket.h>

#include "common/libs/fs/shared_fd.h"
#include "android-base/logging.h"

namespace cuttlefish {
namespace {
// NetlinkClient implementation.
// Talks to libnetlink to apply network changes.
class NetlinkClientImpl : public NetlinkClient {
 public:
  NetlinkClientImpl() = default;
  virtual ~NetlinkClientImpl() = default;

  virtual bool Send(const NetlinkRequest& message);

  // Initialize NetlinkClient instance.
  // Open netlink channel and initialize interface list.
  // Parameter |type| specifies which netlink target to address, eg.
  // NETLINK_ROUTE.
  // Returns true, if initialization was successful.
  bool OpenNetlink(int type);

 private:
  bool CheckResponse(uint32_t seq_no);

  SharedFD netlink_fd_;
  sockaddr_nl address_;
};

bool NetlinkClientImpl::CheckResponse(uint32_t seq_no) {
  uint32_t len;
  char buf[4096];
  struct iovec iov = { buf, sizeof(buf) };
  struct sockaddr_nl sa;
  struct msghdr msg {};
  struct nlmsghdr *nh;

  msg.msg_name = &sa;
  msg.msg_namelen = sizeof(sa);
  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;

  int result = netlink_fd_->RecvMsg(&msg, 0);
  if (result  < 0) {
    LOG(ERROR) << "Netlink error: " << strerror(errno);
    return false;
  }

  len = static_cast<uint32_t>(result);
  LOG(INFO) << "Received netlink response (" << len << " bytes)";

  for (nh = reinterpret_cast<nlmsghdr*>(buf);
       NLMSG_OK(nh, len);
       nh = NLMSG_NEXT(nh, len)) {
    if (nh->nlmsg_seq != seq_no) {
      // This really shouldn't happen. If we see this, it means somebody is
      // issuing netlink requests using the same socket as us, and ignoring
      // responses.
      LOG(WARNING) << "Sequence number mismatch: "
                   << nh->nlmsg_seq << " != " << seq_no;
      continue;
    }

    // This is the end of multi-part message.
    // It indicates there's nothing more netlink wants to tell us.
    // It also means we failed to find the response to our request.
    if (nh->nlmsg_type == NLMSG_DONE)
      break;

    // This is the 'nlmsgerr' package carrying response to our request.
    // It carries an 'error' value (errno) along with the netlink header info
    // that caused this error.
    if (nh->nlmsg_type == NLMSG_ERROR) {
      nlmsgerr* err = reinterpret_cast<nlmsgerr*>(nh + 1);
      if (err->error < 0) {
        LOG(ERROR) << "Failed to complete netlink request: "
                   << "Netlink error: " << err->error
                   << ", errno: " << strerror(errno);
        return false;
      }
      return true;
    }
  }

  LOG(ERROR) << "No response from netlink.";
  return false;
}

bool NetlinkClientImpl::Send(const NetlinkRequest& message) {
  struct sockaddr_nl netlink_addr;
  struct iovec netlink_iov = {
    message.RequestData(),
    message.RequestLength()
  };
  struct msghdr msg;
  memset(&msg, 0, sizeof(msg));
  memset(&netlink_addr, 0, sizeof(netlink_addr));

  msg.msg_name = &address_;
  msg.msg_namelen = sizeof(address_);
  msg.msg_iov = &netlink_iov;
  msg.msg_iovlen = sizeof(netlink_iov) / sizeof(iovec);

  if (netlink_fd_->SendMsg(&msg, 0) < 0) {
    LOG(ERROR) << "Failed to send netlink message: "
               << strerror(errno);

    return false;
  }

  return CheckResponse(message.SeqNo());
}

bool NetlinkClientImpl::OpenNetlink(int type) {
  netlink_fd_ = SharedFD::Socket(AF_NETLINK, SOCK_RAW, type);
  if (!netlink_fd_->IsOpen()) return false;

  address_.nl_family = AF_NETLINK;
  address_.nl_groups = 0;

  netlink_fd_->Bind(reinterpret_cast<sockaddr*>(&address_), sizeof(address_));

  return true;
}

class NetlinkClientFactoryImpl : public NetlinkClientFactory {
 public:
  NetlinkClientFactoryImpl() = default;
  ~NetlinkClientFactoryImpl() override = default;

  std::unique_ptr<NetlinkClient> New(int type) override {
    auto client_raw = new NetlinkClientImpl();
    // Use RVO when possible.
    std::unique_ptr<NetlinkClient> client(client_raw);

    if (!client_raw->OpenNetlink(type)) {
      // Note: deletes client_raw.
      client.reset();
    }
    return client;
  }
};

}  // namespace

NetlinkClientFactory* NetlinkClientFactory::Default() {
  static NetlinkClientFactory &factory = *new NetlinkClientFactoryImpl();
  return &factory;
}

}  // namespace cuttlefish
