/*
 * Copyright (C) 2018 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 <linux/rtnetlink.h>
#include <net/if.h>

#include <array>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>

#include "android-base/logging.h"
#include <cutils/properties.h>
#include <gflags/gflags.h>

#include "common/libs/net/netlink_client.h"
#include "common/libs/net/netlink_request.h"
#include "common/libs/net/network_interface.h"
#include "common/libs/net/network_interface_manager.h"

DEFINE_string(mac_prefix, "", "mac prefix to use for wlan0");

static std::array<unsigned char, 6> prefix_to_mac(
    const std::string& mac_prefix) {
  std::array<unsigned char, 6> mac;
  int macPrefix = stoi(mac_prefix);
  mac[0] = 0x02;
  mac[1] = (macPrefix >> CHAR_BIT) & 0xFF;
  mac[2] = macPrefix & 0xFF;
  return mac;
}

int CreateWifiWrapper(const std::string& source,
                      const std::string& destination) {
  auto factory = cuttlefish::NetlinkClientFactory::Default();
  std::unique_ptr<cuttlefish::NetlinkClient> nl(factory->New(NETLINK_ROUTE));

  LOG(INFO) << "Setting " << source << " mac address based on "
            << FLAGS_mac_prefix;
  int32_t index = if_nametoindex(source.c_str());
  // Setting the address is available in RTM_SETLINK, but not RTM_NEWLINK.
  // https://elixir.bootlin.com/linux/v5.4.44/source/net/core/rtnetlink.c#L2785
  // https://elixir.bootlin.com/linux/v5.4.44/source/net/core/rtnetlink.c#L2460
  // Setting the address seems to work better on the underlying ethernet device,
  // and this mac address is inherited by the virt_wifi device.
  cuttlefish::NetlinkRequest fix_mac_request(
      RTM_SETLINK, NLM_F_REQUEST|NLM_F_ACK|0x600);
  fix_mac_request.Append(ifinfomsg {
    .ifi_index = index,
    .ifi_change = 0xFFFFFFFF,
  });
  fix_mac_request.AddMacAddress(prefix_to_mac(FLAGS_mac_prefix));
  bool fix_mac = nl->Send(fix_mac_request);
  if (!fix_mac) {
    LOG(ERROR) << "setup_network: could not fix mac address";
    return -5;
  }

  // http://maz-programmersdiary.blogspot.com/2011/09/netlink-sockets.html
  cuttlefish::NetlinkRequest link_add_request(RTM_NEWLINK,
                                       NLM_F_REQUEST|NLM_F_ACK|0x600);
  link_add_request.Append(ifinfomsg {
    .ifi_change = 0xFFFFFFFF,
  });
  if (index == 0) {
    LOG(ERROR) << "setup_network: invalid interface name '" << source << "'\n";
    return -2;
  }
  link_add_request.AddString(IFLA_IFNAME, destination);
  link_add_request.AddInt(IFLA_LINK, index);

  link_add_request.PushList(IFLA_LINKINFO);
  link_add_request.AddString(IFLA_INFO_KIND, "virt_wifi");
  link_add_request.PushList(IFLA_INFO_DATA);
  link_add_request.PopList();
  link_add_request.PopList();

  bool link_add_success = nl->Send(link_add_request);
  if (!link_add_success) {
    LOG(ERROR) << "setup_network: could not add link " << destination;
    return -3;
  }

  cuttlefish::NetlinkRequest bring_up_backing_request(RTM_SETLINK,
                                               NLM_F_REQUEST|NLM_F_ACK|0x600);
  bring_up_backing_request.Append(ifinfomsg {
    .ifi_index = index,
    .ifi_flags = IFF_UP,
    .ifi_change = 0xFFFFFFFF,
  });

  bool link_backing_up = nl->Send(bring_up_backing_request);
  if (!link_backing_up) {
    LOG(ERROR) << "setup_network: could not bring up backing " << source;
    return -4;
  }

  return 0;
}

int RenameNetwork(const std::string& name, const std::string& new_name) {
  static auto net_manager =
      cuttlefish::NetworkInterfaceManager::New(cuttlefish::NetlinkClientFactory::Default());
  auto connection = net_manager->Open(name, "ignore");
  if (!connection) {
    LOG(ERROR) << "setup_network: could not open " << name << " on device.";
    return -1;
  }
  connection->SetName(new_name);
  bool changes_applied = net_manager->ApplyChanges(*connection);
  if (!changes_applied) {
    LOG(ERROR) << "setup_network: can't rename " << name << " to " << new_name;
    return -1;
  }
  return 0;
}

int main(int argc, char** argv) {
  char wifi_mac_prefix[PROPERTY_VALUE_MAX + 1];
  property_get("ro.boot.wifi_mac_prefix", wifi_mac_prefix, "");

  SetCommandLineOptionWithMode("mac_prefix", wifi_mac_prefix,
                               google::FlagSettingMode::SET_FLAGS_DEFAULT);

  gflags::ParseCommandLineFlags(&argc, &argv, true);

  int renamed_eth2 = RenameNetwork("eth2", "buried_eth2");
  if (renamed_eth2 != 0) {
    return renamed_eth2;
  }
  return CreateWifiWrapper("buried_eth2", "wlan0");
}
