// Copyright 2012 Google Inc. All Rights Reserved.
// Use of this source code is governed by an Apache-style license that can be
// found in the COPYING file.

#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/network/IOEthernetInterface.h>
#include <IOKit/network/IONetworkInterface.h>
#include <IOKit/network/IOEthernetController.h>

#include "base/logging.h"
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/scoped_ioobject.h"
#include "base/string16.h"
#include "base/stringprintf.h"
#include "base/sys_string_conversions.h"
#include "base/utf_string_conversions.h"

namespace rlz_lib {

namespace {

// See http://developer.apple.com/library/mac/#technotes/tn1103/_index.html

// The caller is responsible for freeing |matching_services|.
bool FindEthernetInterfaces(io_iterator_t* matching_services) {
  base::mac::ScopedCFTypeRef<CFMutableDictionaryRef> matching_dict(
      IOServiceMatching(kIOEthernetInterfaceClass));
  if (!matching_dict)
    return false;

  base::mac::ScopedCFTypeRef<CFMutableDictionaryRef> primary_interface(
      CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
                                &kCFTypeDictionaryKeyCallBacks,
                                &kCFTypeDictionaryValueCallBacks));
  if (!primary_interface)
    return false;

  CFDictionarySetValue(
      primary_interface, CFSTR(kIOPrimaryInterface), kCFBooleanTrue);
  CFDictionarySetValue(
      matching_dict, CFSTR(kIOPropertyMatchKey), primary_interface);

  kern_return_t kern_result = IOServiceGetMatchingServices(
      kIOMasterPortDefault, matching_dict.release(), matching_services);

  return kern_result == KERN_SUCCESS;
}

bool GetMACAddressFromIterator(io_iterator_t primary_interface_iterator,
                               uint8_t* buffer, size_t buffer_size) {
  if (buffer_size < kIOEthernetAddressSize)
    return false;

  bool success = false;

  bzero(buffer, buffer_size);
  base::mac::ScopedIOObject<io_object_t> primary_interface;
  while (primary_interface.reset(IOIteratorNext(primary_interface_iterator)),
         primary_interface) {
    io_object_t primary_interface_parent;
    kern_return_t kern_result = IORegistryEntryGetParentEntry(
        primary_interface, kIOServicePlane, &primary_interface_parent);
    base::mac::ScopedIOObject<io_object_t> primary_interface_parent_deleter(
        primary_interface_parent);
    success = kern_result == KERN_SUCCESS;

    if (!success)
      continue;

    base::mac::ScopedCFTypeRef<CFTypeRef> mac_data(
        IORegistryEntryCreateCFProperty(primary_interface_parent,
                                        CFSTR(kIOMACAddress),
                                        kCFAllocatorDefault,
                                        0));
    CFDataRef mac_data_data = base::mac::CFCast<CFDataRef>(mac_data);
    if (mac_data_data) {
      CFDataGetBytes(
          mac_data_data, CFRangeMake(0, kIOEthernetAddressSize), buffer);
    }
  }

  return success;
}

bool GetMacAddress(unsigned char* buffer, size_t size) {
  io_iterator_t primary_interface_iterator;
  if (!FindEthernetInterfaces(&primary_interface_iterator))
    return false;
  bool result = GetMACAddressFromIterator(
      primary_interface_iterator, buffer, size);
  IOObjectRelease(primary_interface_iterator);
  return result;
}

CFStringRef CopySerialNumber() {
  base::mac::ScopedIOObject<io_service_t> expert_device(
      IOServiceGetMatchingService(kIOMasterPortDefault,
          IOServiceMatching("IOPlatformExpertDevice")));
  if (!expert_device)
    return NULL;

  base::mac::ScopedCFTypeRef<CFTypeRef> serial_number(
      IORegistryEntryCreateCFProperty(expert_device,
                                      CFSTR(kIOPlatformSerialNumberKey),
                                      kCFAllocatorDefault,
                                      0));
  CFStringRef serial_number_cfstring =
      base::mac::CFCast<CFStringRef>(serial_number);
  if (!serial_number_cfstring)
    return NULL;

  ignore_result(serial_number.release());
  return serial_number_cfstring;
}

}  // namespace

bool GetRawMachineId(string16* data, int* more_data) {
  uint8_t mac_address[kIOEthernetAddressSize];

  data->clear();
  if (GetMacAddress(mac_address, sizeof(mac_address))) {
    *data += ASCIIToUTF16(StringPrintf("mac:%02x%02x%02x%02x%02x%02x",
        mac_address[0], mac_address[1], mac_address[2],
        mac_address[3], mac_address[4], mac_address[5]));
  }

  // A MAC address is enough to uniquely identify a machine, but it's only 6
  // bytes, 3 of which are manufacturer-determined. To make brute-forcing the
  // SHA1 of this harder, also append the system's serial number.
  CFStringRef serial = CopySerialNumber();
  if (serial) {
    if (!data->empty())
      *data += UTF8ToUTF16(" ");
    *data += UTF8ToUTF16("serial:") + base::SysCFStringRefToUTF16(serial);
    CFRelease(serial);
  }

  // On windows, this is set to the volume id. Since it's not scrambled before
  // being sent, just set it to 1.
  *more_data = 1;
  return true;
}

}  // namespace rlz_lib
