// Copyright 2018 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.

#include "shill/connection_info_reader.h"

#include <netinet/in.h>

#include <limits>

#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>

#include "shill/file_reader.h"
#include "shill/logging.h"

using base::FilePath;
using std::string;
using std::vector;

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kLink;
static string ObjectID(ConnectionInfoReader* c) {
  return "(connection_info_reader)";
}
}

namespace {

const char kConnectionInfoFilePath[] = "/proc/net/ip_conntrack";
const char kSourceIPAddressTag[] = "src=";
const char kSourcePortTag[] = "sport=";
const char kDestinationIPAddressTag[] = "dst=";
const char kDestinationPortTag[] = "dport=";
const char kUnrepliedTag[] = "[UNREPLIED]";

}  // namespace

ConnectionInfoReader::ConnectionInfoReader() {}

ConnectionInfoReader::~ConnectionInfoReader() {}

FilePath ConnectionInfoReader::GetConnectionInfoFilePath() const {
  return FilePath(kConnectionInfoFilePath);
}

bool ConnectionInfoReader::LoadConnectionInfo(
    vector<ConnectionInfo>* info_list) {
  info_list->clear();

  FilePath info_file_path = GetConnectionInfoFilePath();
  FileReader file_reader;
  if (!file_reader.Open(info_file_path)) {
    SLOG(this, 2) << __func__ << ": Failed to open '"
                  << info_file_path.value() << "'.";
    return false;
  }

  string line;
  while (file_reader.ReadLine(&line)) {
    ConnectionInfo info;
    if (ParseConnectionInfo(line, &info))
      info_list->push_back(info);
  }
  return true;
}

bool ConnectionInfoReader::ParseConnectionInfo(const string& input,
                                               ConnectionInfo* info) {
  vector<string> tokens = base::SplitString(input, base::kWhitespaceASCII,
                                            base::KEEP_WHITESPACE,
                                            base::SPLIT_WANT_NONEMPTY);
  if (tokens.size() < 10) {
    return false;
  }

  ConnectionInfo result;
  int index = 0;

  if (!ParseProtocol(tokens[++index], &result.protocol)) {
    return false;
  }

  if (!ParseTimeToExpireSeconds(tokens[++index],
                                &result.time_to_expire_seconds)) {
    return false;
  }

  if (result.protocol == IPPROTO_TCP)
    ++index;

  bool is_source = false;

  if (!ParseIPAddress(tokens[++index], &result.original_source_ip_address,
                      &is_source) ||
      !is_source) {
    return false;
  }
  if (!ParseIPAddress(tokens[++index], &result.original_destination_ip_address,
                      &is_source) ||
      is_source) {
    return false;
  }

  if (!ParsePort(tokens[++index], &result.original_source_port, &is_source) ||
      !is_source) {
    return false;
  }
  if (!ParsePort(tokens[++index], &result.original_destination_port,
                 &is_source) ||
      is_source) {
    return false;
  }

  if (tokens[index + 1] == kUnrepliedTag) {
    result.is_unreplied = true;
    ++index;
  } else {
    result.is_unreplied = false;
  }

  if (!ParseIPAddress(tokens[++index], &result.reply_source_ip_address,
                      &is_source) ||
      !is_source) {
    return false;
  }
  if (!ParseIPAddress(tokens[++index], &result.reply_destination_ip_address,
                      &is_source) ||
      is_source) {
    return false;
  }

  if (!ParsePort(tokens[++index], &result.reply_source_port, &is_source) ||
      !is_source) {
    return false;
  }
  if (!ParsePort(tokens[++index], &result.reply_destination_port, &is_source) ||
      is_source) {
    return false;
  }

  *info = result;
  return true;
}

bool ConnectionInfoReader::ParseProtocol(const string& input, int* protocol) {
  if (!base::StringToInt(input, protocol) ||
      *protocol < 0 || *protocol >= IPPROTO_MAX) {
    return false;
  }
  return true;
}

bool ConnectionInfoReader::ParseTimeToExpireSeconds(
    const string& input, int64_t* time_to_expire_seconds) {
  if (!base::StringToInt64(input, time_to_expire_seconds) ||
      *time_to_expire_seconds < 0) {
    return false;
  }
  return true;
}

bool ConnectionInfoReader::ParseIPAddress(
    const string& input, IPAddress* ip_address, bool* is_source) {
  string ip_address_string;

  if (base::StartsWith(input, kSourceIPAddressTag,
                       base::CompareCase::INSENSITIVE_ASCII)) {
    *is_source = true;
    ip_address_string = input.substr(strlen(kSourceIPAddressTag));
  } else if (base::StartsWith(input, kDestinationIPAddressTag,
                              base::CompareCase::INSENSITIVE_ASCII)) {
    *is_source = false;
    ip_address_string = input.substr(strlen(kDestinationIPAddressTag));
  } else {
    return false;
  }

  IPAddress ipv4_address(IPAddress::kFamilyIPv4);
  if (ipv4_address.SetAddressFromString(ip_address_string)) {
    *ip_address = ipv4_address;
    return true;
  }

  IPAddress ipv6_address(IPAddress::kFamilyIPv6);
  if (ipv6_address.SetAddressFromString(ip_address_string)) {
    *ip_address = ipv6_address;
    return true;
  }

  return false;
}

bool ConnectionInfoReader::ParsePort(
    const string& input, uint16_t* port, bool* is_source) {
  int result = 0;
  string port_string;

  if (base::StartsWith(input, kSourcePortTag,
                       base::CompareCase::INSENSITIVE_ASCII)) {
    *is_source = true;
    port_string = input.substr(strlen(kSourcePortTag));
  } else if (base::StartsWith(input, kDestinationPortTag,
                              base::CompareCase::INSENSITIVE_ASCII)) {
    *is_source = false;
    port_string = input.substr(strlen(kDestinationPortTag));
  } else {
    return false;
  }

  if (!base::StringToInt(port_string, &result) ||
      result < 0 || result > std::numeric_limits<uint16_t>::max()) {
    return false;
  }

  *port = result;
  return true;
}

}  // namespace shill
