// Copyright (c) 2013 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/string_number_conversions.h>
#include <base/string_split.h>
#include <base/string_util.h>

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

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

namespace shill {

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(Link, 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::SplitStringAlongWhitespace(input, &tokens);
  if (tokens.size() < 10) {
    return false;
  }

  int index = 0;

  int protocol = 0;
  if (!ParseProtocol(tokens[++index], &protocol)) {
    return false;
  }
  info->set_protocol(protocol);

  int64 time_to_expire_seconds = 0;
  if (!ParseTimeToExpireSeconds(tokens[++index], &time_to_expire_seconds)) {
    return false;
  }
  info->set_time_to_expire_seconds(time_to_expire_seconds);

  if (protocol == IPPROTO_TCP)
    ++index;

  IPAddress ip_address(IPAddress::kFamilyUnknown);
  uint16 port = 0;
  bool is_source = false;

  if (!ParseIPAddress(tokens[++index], &ip_address, &is_source) || !is_source) {
    return false;
  }
  info->set_original_source_ip_address(ip_address);
  if (!ParseIPAddress(tokens[++index], &ip_address, &is_source) || is_source) {
    return false;
  }
  info->set_original_destination_ip_address(ip_address);

  if (!ParsePort(tokens[++index], &port, &is_source) || !is_source) {
    return false;
  }
  info->set_original_source_port(port);
  if (!ParsePort(tokens[++index], &port, &is_source) || is_source) {
    return false;
  }
  info->set_original_destination_port(port);

  if (tokens[index + 1] == kUnrepliedTag) {
    info->set_is_unreplied(true);
    ++index;
  } else {
    info->set_is_unreplied(false);
  }

  if (!ParseIPAddress(tokens[++index], &ip_address, &is_source) || !is_source) {
    return false;
  }
  info->set_reply_source_ip_address(ip_address);
  if (!ParseIPAddress(tokens[++index], &ip_address, &is_source) || is_source) {
    return false;
  }
  info->set_reply_destination_ip_address(ip_address);

  if (!ParsePort(tokens[++index], &port, &is_source) || !is_source) {
    return false;
  }
  info->set_reply_source_port(port);
  if (!ParsePort(tokens[++index], &port, &is_source) || is_source) {
    return false;
  }
  info->set_reply_destination_port(port);

  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 *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 (StartsWithASCII(input, kSourceIPAddressTag, false)) {
    *is_source = true;
    ip_address_string = input.substr(strlen(kSourceIPAddressTag));
  } else if (StartsWithASCII(input, kDestinationIPAddressTag, false)) {
    *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 *port, bool *is_source) {
  int result = 0;
  string port_string;

  if (StartsWithASCII(input, kSourcePortTag, false)) {
    *is_source = true;
    port_string = input.substr(strlen(kSourcePortTag));
  } else if (StartsWithASCII(input, kDestinationPortTag, false)) {
    *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>::max()) {
    return false;
  }

  *port = result;
  return true;
}

}  // namespace shill
