blob: 840c5a8b712367116fd6589d655e71a23d89a9ea [file] [log] [blame]
// Copyright (c) 2012 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.
#ifndef SHILL_CONNECTION_H_
#define SHILL_CONNECTION_H_
#include <deque>
#include <string>
#include <vector>
#include <base/memory/ref_counted.h>
#include <base/memory/weak_ptr.h>
#include <gtest/gtest_prod.h> // for FRIEND_TEST
#include "shill/ipconfig.h"
#include "shill/net/ip_address.h"
#include "shill/refptr_types.h"
#include "shill/technology.h"
namespace shill {
class ControlInterface;
class DeviceInfo;
class PermissionBrokerProxyInterface;
class RTNLHandler;
class Resolver;
class RoutingTable;
struct RoutingTableEntry;
// The Conneciton maintains the implemented state of an IPConfig, e.g,
// the IP address, routing table and DNS table entries.
class Connection : public base::RefCounted<Connection> {
public:
// Clients can instantiate and use Binder to bind to a Connection and get
// notified when the bound Connection disconnects. Note that the client's
// disconnect callback will be executed at most once, and only if the bound
// Connection is destroyed or signals disconnect. The Binder unbinds itself
// from the underlying Connection when the Binder instance is destructed.
class Binder {
public:
Binder(const std::string& name, const base::Closure& disconnect_callback);
~Binder();
// Binds to |to_connection|. Unbinds the previous bound connection, if
// any. Pass nullptr to just unbind this Binder.
void Attach(const ConnectionRefPtr& to_connection);
const std::string& name() const { return name_; }
bool IsBound() const { return connection_ != nullptr; }
ConnectionRefPtr connection() const { return connection_.get(); }
private:
friend class Connection;
FRIEND_TEST(ConnectionTest, Binder);
// Invoked by |connection_|.
void OnDisconnect();
const std::string name_;
base::WeakPtr<Connection> connection_;
const base::Closure client_disconnect_callback_;
DISALLOW_COPY_AND_ASSIGN(Binder);
};
Connection(int interface_index,
const std::string& interface_name,
Technology::Identifier technology_,
const DeviceInfo* device_info,
ControlInterface* control_interface);
// Add the contents of an IPConfig reference to the list of managed state.
// This will replace all previous state for this address family.
virtual void UpdateFromIPConfig(const IPConfigRefPtr& config);
// Return the connection used by the lower binder.
virtual ConnectionRefPtr GetLowerConnection() const {
return lower_binder_.connection();
}
// Sets the current connection as "default", i.e., routes and DNS entries
// should be used by all system components that don't select explicitly.
virtual bool is_default() const { return is_default_; }
virtual void SetIsDefault(bool is_default);
// Update and apply the new DNS servers setting to this connection.
virtual void UpdateDNSServers(const std::vector<std::string>& dns_servers);
virtual const std::string& interface_name() const { return interface_name_; }
virtual int interface_index() const { return interface_index_; }
virtual const std::vector<std::string>& dns_servers() const {
return dns_servers_;
}
virtual uint8_t table_id() const { return table_id_; }
virtual const std::string& ipconfig_rpc_identifier() const {
return ipconfig_rpc_identifier_;
}
virtual bool SetupIptableEntries();
virtual bool TearDownIptableEntries();
// Request to accept traffic routed to this connection even if it is not
// the default. This request is ref-counted so the caller must call
// ReleaseRouting() when they no longer need this facility.
virtual void RequestRouting();
virtual void ReleaseRouting();
// Request a host route through this connection.
virtual bool RequestHostRoute(const IPAddress& destination);
// Request a host route through this connection for a list of IPs in CIDR
// notation (|excluded_ips_cidr_|).
virtual bool PinPendingRoutes(int interface_index, RoutingTableEntry entry);
// Return the subnet name for this connection.
virtual std::string GetSubnetName() const;
virtual const IPAddress& local() const { return local_; }
virtual const IPAddress& gateway() const { return gateway_; }
virtual Technology::Identifier technology() const { return technology_; }
virtual const std::string& tethering() const { return tethering_; }
void set_tethering(const std::string& tethering) { tethering_ = tethering; }
// Return the lowest connection on which this connection depends. In case of
// error, a nullptr is returned.
virtual ConnectionRefPtr GetCarrierConnection();
// Return true if this is an IPv6 connection.
virtual bool IsIPv6();
protected:
friend class base::RefCounted<Connection>;
virtual ~Connection();
virtual bool CreateGatewayRoute();
private:
friend class ConnectionTest;
FRIEND_TEST(ConnectionTest, AddConfig);
FRIEND_TEST(ConnectionTest, AddConfigUserTrafficOnly);
FRIEND_TEST(ConnectionTest, Binder);
FRIEND_TEST(ConnectionTest, Binders);
FRIEND_TEST(ConnectionTest, BlackholeIPv6);
FRIEND_TEST(ConnectionTest, Destructor);
FRIEND_TEST(ConnectionTest, FixGatewayReachability);
FRIEND_TEST(ConnectionTest, GetCarrierConnection);
FRIEND_TEST(ConnectionTest, InitState);
FRIEND_TEST(ConnectionTest, OnRouteQueryResponse);
FRIEND_TEST(ConnectionTest, RequestHostRoute);
FRIEND_TEST(ConnectionTest, SetMTU);
FRIEND_TEST(ConnectionTest, UpdateDNSServers);
FRIEND_TEST(VPNServiceTest, OnConnectionDisconnected);
static const uint32_t kDefaultMetric;
static const uint32_t kNonDefaultMetricBase;
static const uint32_t kMarkForUserTraffic;
static const uint8_t kSecondaryTableId;
// Work around misconfigured servers which provide a gateway address that
// is unreachable with the provided netmask.
bool FixGatewayReachability(const IPAddress& local,
IPAddress* peer,
IPAddress* gateway,
const IPAddress& trusted_ip);
uint32_t GetMetric(bool is_default);
bool PinHostRoute(const IPAddress& trusted_ip, const IPAddress& gateway);
void SetMTU(int32_t mtu);
void OnRouteQueryResponse(int interface_index,
const RoutingTableEntry& entry);
void AttachBinder(Binder* binder);
void DetachBinder(Binder* binder);
void NotifyBindersOnDisconnect();
void OnLowerDisconnect();
// Send our DNS configuration to the resolver.
void PushDNSConfig();
base::WeakPtrFactory<Connection> weak_ptr_factory_;
bool is_default_;
bool has_broadcast_domain_;
int routing_request_count_;
int interface_index_;
const std::string interface_name_;
Technology::Identifier technology_;
std::vector<std::string> dns_servers_;
std::vector<std::string> dns_domain_search_;
std::vector<std::string> excluded_ips_cidr_;
std::string dns_domain_name_;
std::string ipconfig_rpc_identifier_;
bool user_traffic_only_;
uint8_t table_id_;
IPAddress local_;
IPAddress gateway_;
// Track the tethering status of the Service associated with this connection.
// This property is set by a service as it takes ownership of a connection,
// and is read by services that are bound through this connection.
std::string tethering_;
// A binder to a lower Connection that this Connection depends on, if any.
Binder lower_binder_;
// Binders to clients -- usually to upper connections or related services and
// devices.
std::deque<Binder*> binders_;
// Store cached copies of singletons for speed/ease of testing
const DeviceInfo* device_info_;
Resolver* resolver_;
RoutingTable* routing_table_;
RTNLHandler* rtnl_handler_;
ControlInterface* control_interface_;
std::unique_ptr<PermissionBrokerProxyInterface> permission_broker_;
DISALLOW_COPY_AND_ASSIGN(Connection);
};
} // namespace shill
#endif // SHILL_CONNECTION_H_