//
// Copyright (C) 2016 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 "dhcp_client/socket_util.h"

#include <linux/filter.h>
#include <linux/if_packet.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_arp.h>

#include <base/logging.h>

#include "dhcp_client/dhcp.h"
#include "shill/net/byte_string.h"
#include "shill/net/sockets.h"

namespace dhcp_client {

namespace {

// Socket filter for dhcp packet.
const sock_filter dhcp_bpf_filter[] = {
  BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23 - ETH_HLEN),
  BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
  BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20 - ETH_HLEN),
  BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
  BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14 - ETH_HLEN),
  BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16 - ETH_HLEN),
  BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP::kDHCPClientPort, 0, 1),
  BPF_STMT(BPF_RET + BPF_K, 0x0fffffff),
  BPF_STMT(BPF_RET + BPF_K, 0),
};

const int dhcp_bpf_filter_len =
    sizeof(dhcp_bpf_filter) / sizeof(dhcp_bpf_filter[0]);

}  // namespace

SocketUtil::SocketUtil(const std::string& interface_name,
                       unsigned int interface_index)
    : sockets_(new shill::Sockets()),
      interface_name_(interface_name),
      interface_index_(interface_index) {
}

SocketUtil::~SocketUtil() {}

bool SocketUtil::CreateUdpSocket(int* udp_socket) {
  // Close previous Udp Socket.
  if (*udp_socket != shill::Sockets::kInvalidFileDescriptor) {
    sockets_->Close(*udp_socket);
    *udp_socket = shill::Sockets::kInvalidFileDescriptor;
  }
  int fd = sockets_->Socket(PF_INET,
                            SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
                            IPPROTO_IP);
  if (fd == shill::Sockets::kInvalidFileDescriptor) {
    PLOG(ERROR) << "Failed to create socket";
    return false;
  }
  shill::ScopedSocketCloser socket_closer(sockets_, fd);

  if (sockets_->ReuseAddress(fd) == -1) {
    PLOG(ERROR) << "Failed to reuse socket address";
    return false;
  }

  if (sockets_->BindToDevice(fd, interface_name_) < 0) {
    PLOG(ERROR) << "Failed to bind socket to device";
    return false;
  }

  struct sockaddr_in local;
  memset(&local, 0, sizeof(local));
  local.sin_family = PF_INET;
  // We do not receive packet from this socket.
  // At this time the ip address may not be setup by shill yet.
  // It is a safe choice to use INADDR_ANY.
  local.sin_addr.s_addr = htonl(INADDR_ANY);
  local.sin_port = htons(DHCP::kDHCPServerPort);

  if (sockets_->Bind(fd,
                     reinterpret_cast<struct sockaddr*>(&local),
                     sizeof(local)) < 0) {
    PLOG(ERROR) << "Failed to bind to address";
    return false;
  }

  *udp_socket = socket_closer.Release();
  return true;
}

bool SocketUtil::CreateRawSocket(int* raw_socket) {
  int fd = sockets_->Socket(PF_PACKET,
                            SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
                            htons(ETHERTYPE_IP));
  if (fd == shill::Sockets::kInvalidFileDescriptor) {
    PLOG(ERROR) << "Failed to create socket";
    return false;
  }
  shill::ScopedSocketCloser socket_closer(sockets_, fd);

  // Apply the socket filter.
  sock_fprog pf;
  memset(&pf, 0, sizeof(pf));
  pf.filter = const_cast<sock_filter*>(dhcp_bpf_filter);
  pf.len = dhcp_bpf_filter_len;

  if (sockets_->AttachFilter(fd, &pf) != 0) {
    PLOG(ERROR) << "Failed to attach filter";
    return false;
  }

  if (sockets_->ReuseAddress(fd) == -1) {
    PLOG(ERROR) << "Failed to reuse socket address";
    return false;
  }

  if (sockets_->BindToDevice(fd, interface_name_) < 0) {
    PLOG(ERROR) << "Failed to bind socket to device";
    return false;
  }

  struct sockaddr_ll local;
  memset(&local, 0, sizeof(local));
  local.sll_family = PF_PACKET;
  local.sll_protocol = htons(ETHERTYPE_IP);
  local.sll_ifindex = static_cast<int>(interface_index_);

  if (sockets_->Bind(fd,
                     reinterpret_cast<struct sockaddr*>(&local),
                     sizeof(local)) < 0) {
    PLOG(ERROR) << "Failed to bind to address";
    return false;
  }

  *raw_socket = socket_closer.Release();
  return true;
}

bool SocketUtil::SendBroadcastPacket(int raw_socket,
                                     const shill::ByteString& packet) {
  LOG(INFO) << __func__;
  struct sockaddr_ll remote;
  memset(&remote, 0, sizeof(remote));
  remote.sll_family = AF_PACKET;
  remote.sll_protocol = htons(ETHERTYPE_IP);
  remote.sll_ifindex = interface_index_;
  remote.sll_hatype = htons(ARPHRD_ETHER);
  // Use broadcast hardware address.
  remote.sll_halen = IFHWADDRLEN;
  memset(remote.sll_addr, 0xff, IFHWADDRLEN);

  size_t result = sockets_->SendTo(raw_socket,
                                   packet.GetConstData(),
                                   packet.GetLength(),
                                   0,
                                   reinterpret_cast<struct sockaddr *>(&remote),
                                   sizeof(remote));

  if (result != packet.GetLength()) {
    PLOG(ERROR) << "Socket sento failed";
    return false;
  }
  return true;
}

bool SocketUtil::SendUnicastPacket(int udp_socket,
                                   const shill::ByteString& packet,
                                   uint32_t server_ip) {
  LOG(INFO) << __func__;
  struct sockaddr_in remote;
  memset(&remote, 0, sizeof(remote));
  remote.sin_family = AF_INET;
  remote.sin_port = htons(DHCP::kDHCPServerPort);
  remote.sin_addr.s_addr = htonl(server_ip);

  size_t result = sockets_->SendTo(udp_socket,
                                   packet.GetConstData(),
                                   packet.GetLength(),
                                   0,
                                   reinterpret_cast<struct sockaddr *>(&remote),
                                   sizeof(remote));

  if (result != packet.GetLength()) {
    PLOG(ERROR) << "Socket sento failed";
    return false;
  }
  return true;
}

}  // namespace dhcp_client
