// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This code is derived from the 'iw' source code.  The copyright and license
// of that code is as follows:
//
// Copyright (c) 2007, 2008  Johannes Berg
// Copyright (c) 2007  Andy Lutomirski
// Copyright (c) 2007  Mike Kershaw
// Copyright (c) 2008-2009  Luis R. Rodriguez
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#include "shill/netlink_socket.h"

#include <ctype.h>
#include <errno.h>
#include <string.h>

#include <net/if.h>
#include <netlink/attr.h>
#include <netlink/genl/ctrl.h>
#include <netlink/genl/family.h>
#include <netlink/genl/genl.h>
#include <netlink/msg.h>
#include <netlink/netlink.h>

#include <iomanip>

#include "shill/logging.h"

namespace shill {

//
// NetlinkSocket::Callback.
//

NetlinkSocket::Callback::~Callback() {
  if (cb_) {
    nl_cb_put(cb_);
    cb_ = NULL;
  }
}

bool NetlinkSocket::Callback::Init() {
  cb_ = nl_cb_alloc(NL_CB_DEFAULT);
  if (!cb_) {
    LOG(ERROR) << "NULL cb_";
    return false;
  }
  return true;
}

bool NetlinkSocket::Callback::ErrHandler(enum nl_cb_kind kind,
                                         nl_recvmsg_err_cb_t func,
                                         void *arg) {
  int result = nl_cb_err(cb_, kind, func, arg);
  if (result) {
    LOG(ERROR) << "nl_cb_err returned " << result;
    return false;
  }
  return true;
}

bool NetlinkSocket::Callback::SetHandler(enum nl_cb_type type,
                                         enum nl_cb_kind kind,
                                         nl_recvmsg_msg_cb_t func,
                                         void *arg) {
  int result = nl_cb_set(cb_, type, kind, func, arg);
  if (result) {
    LOG(ERROR) << "nl_cb_set returned " << result;
    return false;
  }
  return true;
}

//
// NetlinkSocket.
//

NetlinkSocket::~NetlinkSocket() {
  if (nl_sock_) {
    nl_socket_free(nl_sock_);
    nl_sock_ = NULL;
  }
}

bool NetlinkSocket::Init() {
  nl_sock_ = nl_socket_alloc();
  if (!nl_sock_) {
    LOG(ERROR) << "Failed to allocate netlink socket.";
    return false;
  }

  if (genl_connect(nl_sock_)) {
    LOG(ERROR) << "Failed to connect to generic netlink.";
    return false;
  }

  return true;
}

uint32 NetlinkSocket::Send(struct nl_msg *message,
                           uint8 command,
                           int32 family_id) {
  if (!message) {
    LOG(ERROR) << "NULL |message|.";
    return 0;
  }

  if (!nl_sock_) {
    LOG(ERROR) << "Need to initialize the socket first.";
    return 0;
  }

  // Parameters to genlmsg_put:
  //  @message: a pointer to a struct nl_msg *message.
  //  @pid: netlink pid the message is addressed to.
  //  @seq: sequence number.
  //  @family: netlink socket family (NETLINK_GENERIC for us)
  //  @flags netlink message flags.
  //  @hdrlen: Length of a user header (which we don't use)
  //  @cmd: netlink command.
  //  @version: version of communication protocol.
  // genlmsg_put returns a void * pointing to the user header but we don't
  // want to encourage its use outside of this object.

  uint32 sequence_number = GetSequenceNumber();
  if (genlmsg_put(message, NL_AUTO_PID, sequence_number, family_id,
                  0, 0, command, 0) == NULL) {
    LOG(ERROR) << "genlmsg_put returned a NULL pointer.";
    return 0;
  }

  SLOG(WiFi, 6) << "NL Message " << sequence_number << " ===>";

  int result = nl_send_auto_complete(nl_sock_, message);
  if (result < 0) {
    LOG(ERROR) << "Failed call to 'nl_send_auto_complete': " << result;
    return 0;
  }
  return sequence_number;
}


bool NetlinkSocket::DisableSequenceChecking() {
  if (!nl_sock_) {
    LOG(ERROR) << "NULL socket";
    return false;
  }

  // NOTE: can't use nl_socket_disable_seq_check(); it's not in this version
  // of the library.
  int result = nl_socket_modify_cb(nl_sock_, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
                                   NetlinkSocket::IgnoreSequenceCheck, NULL);
  if (result) {
    LOG(ERROR) << "Failed call to nl_socket_modify_cb: " << result;
    return false;
  }

  return true;
}

int NetlinkSocket::GetFd() const {
  if (!nl_sock_) {
    LOG(ERROR) << "NULL socket";
    return -1;
  }
  return nl_socket_get_fd(nl_sock_);
}

bool NetlinkSocket::GetMessages() {
  // TODO(wdg): make this non-blocking.
  // Blocks until a message is available.  When that happens, the message is
  // read and passed to the default callback (i.e., the one set with
  // NetlinkSocket::SetNetlinkCallback).
  int result = nl_recvmsgs_default(nl_sock_);
  if (result < 0) {
    LOG(ERROR) << "Failed call to nl_recvmsgs_default: " << strerror(-result)
               << " (" << result << ")";
    return false;
  }
  return true;
}

bool NetlinkSocket::GetMessagesUsingCallback(
    NetlinkSocket::Callback *on_netlink_data) {
  if (!on_netlink_data || !on_netlink_data->cb_)
    return GetMessages();  // Default to generic callback.

  int result = nl_recvmsgs(nl_sock_, on_netlink_data->cb_);
  if (result < 0) {
    LOG(ERROR) << "Failed call to nl_recvmsgs: " << strerror(-result)
               << " (" << result << ")";
    return false;
  }
  return true;
}

unsigned int NetlinkSocket::GetSequenceNumber() {
  unsigned int number = nl_socket_use_seq(nl_sock_);
  if (number == 0) {
    number = nl_socket_use_seq(nl_sock_);
  }
  if (number == 0) {
    LOG(WARNING) << "Couldn't get non-zero sequence number";
    number = 1;
  }
  return number;
}

bool NetlinkSocket::SetNetlinkCallback(nl_recvmsg_msg_cb_t on_netlink_data,
                                       void *callback_parameter) {
  if (!nl_sock_) {
    LOG(ERROR) << "NULL socket";
    return false;
  }

  int result = nl_socket_modify_cb(nl_sock_, NL_CB_VALID, NL_CB_CUSTOM,
                                   on_netlink_data, callback_parameter);
  if (result) {
    LOG(ERROR) << "nl_socket_modify_cb returned " << strerror(-result)
               << " (" << result << ")";
    return false;
  }
  return true;
}

int NetlinkSocket::IgnoreSequenceCheck(struct nl_msg *ignored_msg,
                                       void *ignored_arg) {
  return NL_OK;  // Proceed.
}

}  // namespace shill.
