diff --git a/buffet/shill_client.cc b/buffet/shill_client.cc
new file mode 100644
index 0000000..1efc52d
--- /dev/null
+++ b/buffet/shill_client.cc
@@ -0,0 +1,487 @@
+// Copyright 2014 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 "buffet/shill_client.h"
+
+#include <set>
+
+#include <base/message_loop/message_loop.h>
+#include <base/stl_util.h>
+#include <chromeos/any.h>
+#include <chromeos/dbus/service_constants.h>
+#include <chromeos/errors/error.h>
+#include <chromeos/errors/error_codes.h>
+
+#include "weave/enum_to_string.h"
+
+using chromeos::Any;
+using chromeos::VariantDictionary;
+using dbus::ObjectPath;
+using org::chromium::flimflam::DeviceProxy;
+using org::chromium::flimflam::ServiceProxy;
+using std::map;
+using std::set;
+using std::string;
+using std::vector;
+
+namespace buffet {
+
+namespace {
+
+void IgnoreDetachEvent() {}
+
+bool GetStateForService(ServiceProxy* service, string* state) {
+  CHECK(service) << "|service| was nullptr in GetStateForService()";
+  VariantDictionary properties;
+  if (!service->GetProperties(&properties, nullptr)) {
+    LOG(WARNING) << "Failed to read properties from service.";
+    return false;
+  }
+  auto property_it = properties.find(shill::kStateProperty);
+  if (property_it == properties.end()) {
+    LOG(WARNING) << "No state found in service properties.";
+    return false;
+  }
+  string new_state = property_it->second.TryGet<string>();
+  if (new_state.empty()) {
+    LOG(WARNING) << "Invalid state value.";
+    return false;
+  }
+  *state = new_state;
+  return true;
+}
+
+weave::NetworkState ShillServiceStateToNetworkState(const string& state) {
+  // TODO(wiley) What does "unconfigured" mean in a world with multiple sets
+  //             of WiFi credentials?
+  // TODO(wiley) Detect disabled devices, update state appropriately.
+  if ((state.compare(shill::kStateReady) == 0) ||
+      (state.compare(shill::kStatePortal) == 0) ||
+      (state.compare(shill::kStateOnline) == 0)) {
+    return weave::NetworkState::kConnected;
+  }
+  if ((state.compare(shill::kStateAssociation) == 0) ||
+      (state.compare(shill::kStateConfiguration) == 0)) {
+    return weave::NetworkState::kConnecting;
+  }
+  if ((state.compare(shill::kStateFailure) == 0) ||
+      (state.compare(shill::kStateActivationFailure) == 0)) {
+    // TODO(wiley) Get error information off the service object.
+    return weave::NetworkState::kFailure;
+  }
+  if ((state.compare(shill::kStateIdle) == 0) ||
+      (state.compare(shill::kStateOffline) == 0) ||
+      (state.compare(shill::kStateDisconnect) == 0)) {
+    return weave::NetworkState::kOffline;
+  }
+  LOG(WARNING) << "Unknown state found: '" << state << "'";
+  return weave::NetworkState::kOffline;
+}
+
+}  // namespace
+
+ShillClient::ShillClient(const scoped_refptr<dbus::Bus>& bus,
+                         const set<string>& device_whitelist)
+    : bus_{bus},
+      manager_proxy_{bus_, ObjectPath{"/"}},
+      device_whitelist_{device_whitelist} {
+  manager_proxy_.RegisterPropertyChangedSignalHandler(
+      base::Bind(&ShillClient::OnManagerPropertyChange,
+                 weak_factory_.GetWeakPtr()),
+      base::Bind(&ShillClient::OnManagerPropertyChangeRegistration,
+                 weak_factory_.GetWeakPtr()));
+  auto owner_changed_cb = base::Bind(&ShillClient::OnShillServiceOwnerChange,
+                                     weak_factory_.GetWeakPtr());
+  bus_->GetObjectProxy(shill::kFlimflamServiceName, ObjectPath{"/"})
+      ->SetNameOwnerChangedCallback(owner_changed_cb);
+}
+
+void ShillClient::Init() {
+  VLOG(2) << "ShillClient::Init();";
+  CleanupConnectingService(false);
+  devices_.clear();
+  connectivity_state_ = weave::NetworkState::kOffline;
+  VariantDictionary properties;
+  if (!manager_proxy_.GetProperties(&properties, nullptr)) {
+    LOG(ERROR) << "Unable to get properties from Manager, waiting for "
+                  "Manager to come back online.";
+    return;
+  }
+  auto it = properties.find(shill::kDevicesProperty);
+  CHECK(it != properties.end()) << "shill should always publish a device list.";
+  OnManagerPropertyChange(shill::kDevicesProperty, it->second);
+}
+
+bool ShillClient::ConnectToService(const string& ssid,
+                                   const string& passphrase,
+                                   const base::Closure& on_success,
+                                   chromeos::ErrorPtr* error) {
+  CleanupConnectingService(false);
+  VariantDictionary service_properties;
+  service_properties[shill::kTypeProperty] = Any{string{shill::kTypeWifi}};
+  service_properties[shill::kSSIDProperty] = Any{ssid};
+  service_properties[shill::kPassphraseProperty] = Any{passphrase};
+  service_properties[shill::kSecurityProperty] = Any{
+      string{passphrase.empty() ? shill::kSecurityNone : shill::kSecurityPsk}};
+  service_properties[shill::kSaveCredentialsProperty] = Any{true};
+  service_properties[shill::kAutoConnectProperty] = Any{true};
+  ObjectPath service_path;
+  if (!manager_proxy_.ConfigureService(service_properties, &service_path,
+                                       error)) {
+    return false;
+  }
+  if (!manager_proxy_.RequestScan(shill::kTypeWifi, error)) {
+    return false;
+  }
+  connecting_service_.reset(new ServiceProxy{bus_, service_path});
+  on_connect_success_.Reset(on_success);
+  connecting_service_->RegisterPropertyChangedSignalHandler(
+      base::Bind(&ShillClient::OnServicePropertyChange,
+                 weak_factory_.GetWeakPtr(), service_path),
+      base::Bind(&ShillClient::OnServicePropertyChangeRegistration,
+                 weak_factory_.GetWeakPtr(), service_path));
+  return true;
+}
+
+weave::NetworkState ShillClient::GetConnectionState() const {
+  return connectivity_state_;
+}
+
+void ShillClient::AddOnConnectionChangedCallback(
+    const OnConnectionChangedCallback& listener) {
+  connectivity_listeners_.push_back(listener);
+}
+
+bool ShillClient::IsMonitoredDevice(DeviceProxy* device) {
+  if (device_whitelist_.empty()) {
+    return true;
+  }
+  VariantDictionary device_properties;
+  if (!device->GetProperties(&device_properties, nullptr)) {
+    LOG(ERROR) << "Devices without properties aren't whitelisted.";
+    return false;
+  }
+  auto it = device_properties.find(shill::kInterfaceProperty);
+  if (it == device_properties.end()) {
+    LOG(ERROR) << "Failed to find interface property in device properties.";
+    return false;
+  }
+  return ContainsKey(device_whitelist_, it->second.TryGet<string>());
+}
+
+void ShillClient::OnShillServiceOwnerChange(const string& old_owner,
+                                            const string& new_owner) {
+  VLOG(1) << "Shill service owner name changed to '" << new_owner << "'";
+  if (new_owner.empty()) {
+    CleanupConnectingService(false);
+    devices_.clear();
+    connectivity_state_ = weave::NetworkState::kOffline;
+  } else {
+    Init();  // New service owner means shill reset!
+  }
+}
+
+void ShillClient::OnManagerPropertyChangeRegistration(const string& interface,
+                                                      const string& signal_name,
+                                                      bool success) {
+  VLOG(3) << "Registered ManagerPropertyChange handler.";
+  CHECK(success) << "privetd requires Manager signals.";
+  VariantDictionary properties;
+  if (!manager_proxy_.GetProperties(&properties, nullptr)) {
+    LOG(ERROR) << "Unable to get properties from Manager, waiting for "
+                  "Manager to come back online.";
+    return;
+  }
+  auto it = properties.find(shill::kDevicesProperty);
+  CHECK(it != properties.end()) << "Shill should always publish a device list.";
+  OnManagerPropertyChange(shill::kDevicesProperty, it->second);
+}
+
+void ShillClient::OnManagerPropertyChange(const string& property_name,
+                                          const Any& property_value) {
+  if (property_name != shill::kDevicesProperty) {
+    return;
+  }
+  VLOG(3) << "Manager's device list has changed.";
+  // We're going to remove every device we haven't seen in the update.
+  set<ObjectPath> device_paths_to_remove;
+  for (const auto& kv : devices_) {
+    device_paths_to_remove.insert(kv.first);
+  }
+  for (const auto& device_path : property_value.TryGet<vector<ObjectPath>>()) {
+    if (!device_path.IsValid()) {
+      LOG(ERROR) << "Ignoring invalid device path in Manager's device list.";
+      return;
+    }
+    auto it = devices_.find(device_path);
+    if (it != devices_.end()) {
+      // Found an existing proxy.  Since the whitelist never changes,
+      // this still a valid device.
+      device_paths_to_remove.erase(device_path);
+      continue;
+    }
+    std::unique_ptr<DeviceProxy> device{new DeviceProxy{bus_, device_path}};
+    if (!IsMonitoredDevice(device.get())) {
+      continue;
+    }
+    device->RegisterPropertyChangedSignalHandler(
+        base::Bind(&ShillClient::OnDevicePropertyChange,
+                   weak_factory_.GetWeakPtr(), device_path),
+        base::Bind(&ShillClient::OnDevicePropertyChangeRegistration,
+                   weak_factory_.GetWeakPtr(), device_path));
+    VLOG(3) << "Creating device proxy at " << device_path.value();
+    devices_[device_path].device = std::move(device);
+  }
+  // Clean up devices/services related to removed devices.
+  if (!device_paths_to_remove.empty()) {
+    for (const ObjectPath& device_path : device_paths_to_remove) {
+      devices_.erase(device_path);
+    }
+    UpdateConnectivityState();
+  }
+}
+
+void ShillClient::OnDevicePropertyChangeRegistration(
+    const ObjectPath& device_path,
+    const string& interface,
+    const string& signal_name,
+    bool success) {
+  VLOG(3) << "Registered DevicePropertyChange handler.";
+  auto it = devices_.find(device_path);
+  if (it == devices_.end()) {
+    return;
+  }
+  CHECK(success) << "Failed to subscribe to Device property changes.";
+  DeviceProxy* device = it->second.device.get();
+  VariantDictionary properties;
+  if (!device->GetProperties(&properties, nullptr)) {
+    LOG(WARNING) << "Failed to get device properties?";
+    return;
+  }
+  auto prop_it = properties.find(shill::kSelectedServiceProperty);
+  if (prop_it == properties.end()) {
+    LOG(WARNING) << "Failed to get device's selected service?";
+    return;
+  }
+  OnDevicePropertyChange(device_path, shill::kSelectedServiceProperty,
+                         prop_it->second);
+}
+
+void ShillClient::OnDevicePropertyChange(const ObjectPath& device_path,
+                                         const string& property_name,
+                                         const Any& property_value) {
+  // We only care about selected services anyway.
+  if (property_name != shill::kSelectedServiceProperty) {
+    return;
+  }
+  // If the device isn't our list of whitelisted devices, ignore it.
+  auto it = devices_.find(device_path);
+  if (it == devices_.end()) {
+    return;
+  }
+  DeviceState& device_state = it->second;
+  ObjectPath service_path{property_value.TryGet<ObjectPath>()};
+  if (!service_path.IsValid()) {
+    LOG(ERROR) << "Device at " << device_path.value()
+               << " selected invalid service path.";
+    return;
+  }
+  VLOG(3) << "Device at " << it->first.value() << " has selected service at "
+          << service_path.value();
+  bool removed_old_service{false};
+  if (device_state.selected_service) {
+    if (device_state.selected_service->GetObjectPath() == service_path) {
+      return;  // Spurious update?
+    }
+    device_state.selected_service.reset();
+    device_state.service_state = weave::NetworkState::kOffline;
+    removed_old_service = true;
+  }
+  std::shared_ptr<ServiceProxy> new_service;
+  const bool reuse_connecting_service =
+      service_path.value() != "/" && connecting_service_ &&
+      connecting_service_->GetObjectPath() == service_path;
+  if (reuse_connecting_service) {
+    new_service = connecting_service_;
+    // When we reuse the connecting service, we need to make sure that our
+    // cached state is correct.  Normally, we do this by relying reading the
+    // state when our signal handlers finish registering, but this may have
+    // happened long in the past for the connecting service.
+    string state;
+    if (GetStateForService(new_service.get(), &state)) {
+      device_state.service_state = ShillServiceStateToNetworkState(state);
+    } else {
+      LOG(WARNING) << "Failed to read properties from existing service "
+                      "on selection.";
+    }
+  } else if (service_path.value() != "/") {
+    // The device has selected a new service we haven't see before.
+    new_service.reset(new ServiceProxy{bus_, service_path});
+    new_service->RegisterPropertyChangedSignalHandler(
+        base::Bind(&ShillClient::OnServicePropertyChange,
+                   weak_factory_.GetWeakPtr(), service_path),
+        base::Bind(&ShillClient::OnServicePropertyChangeRegistration,
+                   weak_factory_.GetWeakPtr(), service_path));
+  }
+  device_state.selected_service = new_service;
+  if (reuse_connecting_service || removed_old_service) {
+    UpdateConnectivityState();
+  }
+}
+
+void ShillClient::OnServicePropertyChangeRegistration(const ObjectPath& path,
+                                                      const string& interface,
+                                                      const string& signal_name,
+                                                      bool success) {
+  VLOG(3) << "OnServicePropertyChangeRegistration(" << path.value() << ");";
+  ServiceProxy* service{nullptr};
+  if (connecting_service_ && connecting_service_->GetObjectPath() == path) {
+    // Note that the connecting service might also be a selected service.
+    service = connecting_service_.get();
+    if (!success) {
+      CleanupConnectingService(false);
+    }
+  } else {
+    for (const auto& kv : devices_) {
+      if (kv.second.selected_service &&
+          kv.second.selected_service->GetObjectPath() == path) {
+        service = kv.second.selected_service.get();
+        break;
+      }
+    }
+  }
+  if (service == nullptr || !success) {
+    return;  // A failure or success for a proxy we no longer care about.
+  }
+  VariantDictionary properties;
+  if (!service->GetProperties(&properties, nullptr)) {
+    return;
+  }
+  // Give ourselves property changed signals for the initial property
+  // values.
+  auto it = properties.find(shill::kStateProperty);
+  if (it != properties.end()) {
+    OnServicePropertyChange(path, shill::kStateProperty, it->second);
+  }
+  it = properties.find(shill::kSignalStrengthProperty);
+  if (it != properties.end()) {
+    OnServicePropertyChange(path, shill::kSignalStrengthProperty, it->second);
+  }
+}
+
+void ShillClient::OnServicePropertyChange(const ObjectPath& service_path,
+                                          const string& property_name,
+                                          const Any& property_value) {
+  VLOG(3) << "ServicePropertyChange(" << service_path.value() << ", "
+          << property_name << ", ...);";
+  if (property_name == shill::kStateProperty) {
+    const string state{property_value.TryGet<string>()};
+    if (state.empty()) {
+      VLOG(3) << "Invalid service state update.";
+      return;
+    }
+    VLOG(3) << "New service state=" << state;
+    OnStateChangeForSelectedService(service_path, state);
+    OnStateChangeForConnectingService(service_path, state);
+  } else if (property_name == shill::kSignalStrengthProperty) {
+    OnStrengthChangeForConnectingService(service_path,
+                                         property_value.TryGet<uint8_t>());
+  }
+}
+
+void ShillClient::OnStateChangeForConnectingService(
+    const ObjectPath& service_path,
+    const string& state) {
+  if (!connecting_service_ ||
+      connecting_service_->GetObjectPath() != service_path ||
+      ShillServiceStateToNetworkState(state) !=
+          weave::NetworkState::kConnected) {
+    return;
+  }
+  connecting_service_reset_pending_ = true;
+  on_connect_success_.callback().Run();
+  CleanupConnectingService(true);
+}
+
+void ShillClient::OnStrengthChangeForConnectingService(
+    const ObjectPath& service_path,
+    uint8_t signal_strength) {
+  if (!connecting_service_ ||
+      connecting_service_->GetObjectPath() != service_path ||
+      signal_strength <= 0 || have_called_connect_) {
+    return;
+  }
+  VLOG(1) << "Connecting service has signal. Calling Connect().";
+  have_called_connect_ = true;
+  // Failures here indicate that we've already connected,
+  // or are connecting, or some other very unexciting thing.
+  // Ignore all that, and rely on state changes to detect
+  // connectivity.
+  connecting_service_->Connect(nullptr);
+}
+
+void ShillClient::OnStateChangeForSelectedService(
+    const ObjectPath& service_path,
+    const string& state) {
+  // Find the device/service pair responsible for this update
+  VLOG(3) << "State for potentially selected service " << service_path.value()
+          << " have changed to " << state;
+  for (auto& kv : devices_) {
+    if (kv.second.selected_service &&
+        kv.second.selected_service->GetObjectPath() == service_path) {
+      VLOG(3) << "Updated cached connection state for selected service.";
+      kv.second.service_state = ShillServiceStateToNetworkState(state);
+      UpdateConnectivityState();
+      return;
+    }
+  }
+}
+
+void ShillClient::UpdateConnectivityState() {
+  // Update the connectivity state of the device by picking the
+  // state of the currently most connected selected service.
+  weave::NetworkState new_connectivity_state{weave::NetworkState::kOffline};
+  for (const auto& kv : devices_) {
+    if (kv.second.service_state > new_connectivity_state) {
+      new_connectivity_state = kv.second.service_state;
+    }
+  }
+  VLOG(1) << "Connectivity changed: " << EnumToString(connectivity_state_)
+          << " -> " << EnumToString(new_connectivity_state);
+  // Notify listeners even if state changed to the same value. Listeners may
+  // want to handle this event.
+  connectivity_state_ = new_connectivity_state;
+  // We may call UpdateConnectivityState whenever we mutate a data structure
+  // such that our connectivity status could change.  However, we don't want
+  // to allow people to call into ShillClient while some other operation is
+  // underway.  Therefore, call our callbacks later, when we're in a good
+  // state.
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&ShillClient::NotifyConnectivityListeners,
+                 weak_factory_.GetWeakPtr(),
+                 GetConnectionState() == weave::NetworkState::kConnected));
+}
+
+void ShillClient::NotifyConnectivityListeners(bool am_online) {
+  VLOG(3) << "Notifying connectivity listeners that online=" << am_online;
+  for (const auto& listener : connectivity_listeners_) {
+    listener.Run(am_online);
+  }
+}
+
+void ShillClient::CleanupConnectingService(bool check_for_reset_pending) {
+  if (check_for_reset_pending && !connecting_service_reset_pending_) {
+    return;  // Must have called connect before we got here.
+  }
+  if (connecting_service_) {
+    connecting_service_->ReleaseObjectProxy(base::Bind(&IgnoreDetachEvent));
+    connecting_service_.reset();
+  }
+  on_connect_success_.Cancel();
+  have_called_connect_ = false;
+  connecting_service_reset_pending_ = false;
+}
+
+}  // namespace buffet
