| // 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_ |
| #define SHILL_CONNECTION_ |
| |
| #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/ip_address.h" |
| #include "shill/ipconfig.h" |
| #include "shill/refptr_types.h" |
| #include "shill/technology.h" |
| |
| namespace shill { |
| |
| class DeviceInfo; |
| 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 NULL to just unbind this Binder. |
| void Attach(const ConnectionRefPtr &to_connection); |
| |
| const std::string &name() const { return name_; } |
| bool IsBound() const { return connection_ != NULL; } |
| 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); |
| |
| // 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); |
| |
| 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 const std::string &ipconfig_rpc_identifier() const { |
| return ipconfig_rpc_identifier_; |
| } |
| |
| // 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); |
| |
| virtual const IPAddress &local() const { return local_; } |
| virtual const IPAddress &gateway() const { return gateway_; } |
| virtual Technology::Identifier technology() const { return technology_; } |
| |
| // Return the lowest connection on which this connection depends. In case of |
| // error, a NULL is returned. |
| virtual ConnectionRefPtr GetCarrierConnection(); |
| |
| protected: |
| friend class base::RefCounted<Connection>; |
| |
| virtual ~Connection(); |
| virtual bool CreateGatewayRoute(); |
| |
| private: |
| friend class ConnectionTest; |
| FRIEND_TEST(ConnectionTest, AddConfig); |
| FRIEND_TEST(ConnectionTest, Binder); |
| FRIEND_TEST(ConnectionTest, Binders); |
| 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, BlackholeIPv6); |
| FRIEND_TEST(VPNServiceTest, OnConnectionDisconnected); |
| |
| static const uint32 kDefaultMetric; |
| static const uint32 kNonDefaultMetricBase; |
| |
| // Work around misconfigured servers which provide a gateway address that |
| // is unreachable with the provided netmask. |
| static bool FixGatewayReachability(IPAddress *local, |
| IPAddress *peer, |
| IPAddress *gateway, |
| const IPAddress &trusted_ip); |
| uint32 GetMetric(bool is_default); |
| bool PinHostRoute(const IPAddress &trusted_ip, const IPAddress &gateway); |
| |
| 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::string dns_domain_name_; |
| std::string ipconfig_rpc_identifier_; |
| IPAddress local_; |
| IPAddress gateway_; |
| |
| // 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_; |
| |
| DISALLOW_COPY_AND_ASSIGN(Connection); |
| }; |
| |
| } // namespace shill |
| |
| #endif // SHILL_CONNECTION_ |