diff options
author | henrike@webrtc.org <henrike@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> | 2014-05-13 18:00:26 +0000 |
---|---|---|
committer | henrike@webrtc.org <henrike@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> | 2014-05-13 18:00:26 +0000 |
commit | f048872e915a3ee229044ec4bc541f6cbf9e4de1 (patch) | |
tree | df6a85065b81a76772d3a23dc9eac919a2134ce4 /webrtc/base/firewallsocketserver.cc | |
parent | 3e01e0b16cbde481241b9bcfdbbdd591cd920b99 (diff) | |
download | webrtc-f048872e915a3ee229044ec4bc541f6cbf9e4de1.tar.gz |
Adds a modified copy of talk/base to webrtc/base. It is the first step in
migrating talk/base to webrtc/base.
BUG=N/A
R=niklas.enbom@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/17479005
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6129 4adac7df-926f-26a2-2b94-8c16560cd09d
Diffstat (limited to 'webrtc/base/firewallsocketserver.cc')
-rw-r--r-- | webrtc/base/firewallsocketserver.cc | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/webrtc/base/firewallsocketserver.cc b/webrtc/base/firewallsocketserver.cc new file mode 100644 index 0000000000..31c18d9817 --- /dev/null +++ b/webrtc/base/firewallsocketserver.cc @@ -0,0 +1,239 @@ +/* + * Copyright 2004 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/base/firewallsocketserver.h" + +#include <assert.h> + +#include <algorithm> + +#include "webrtc/base/asyncsocket.h" +#include "webrtc/base/logging.h" + +namespace rtc { + +class FirewallSocket : public AsyncSocketAdapter { + public: + FirewallSocket(FirewallSocketServer* server, AsyncSocket* socket, int type) + : AsyncSocketAdapter(socket), server_(server), type_(type) { + } + + virtual int Connect(const SocketAddress& addr) { + if (type_ == SOCK_STREAM) { + if (!server_->Check(FP_TCP, GetLocalAddress(), addr)) { + LOG(LS_VERBOSE) << "FirewallSocket outbound TCP connection from " + << GetLocalAddress().ToSensitiveString() << " to " + << addr.ToSensitiveString() << " denied"; + // TODO: Handle this asynchronously. + SetError(EHOSTUNREACH); + return SOCKET_ERROR; + } + } + return AsyncSocketAdapter::Connect(addr); + } + virtual int Send(const void* pv, size_t cb) { + return SendTo(pv, cb, GetRemoteAddress()); + } + virtual int SendTo(const void* pv, size_t cb, const SocketAddress& addr) { + if (type_ == SOCK_DGRAM) { + if (!server_->Check(FP_UDP, GetLocalAddress(), addr)) { + LOG(LS_VERBOSE) << "FirewallSocket outbound UDP packet from " + << GetLocalAddress().ToSensitiveString() << " to " + << addr.ToSensitiveString() << " dropped"; + return static_cast<int>(cb); + } + } + return AsyncSocketAdapter::SendTo(pv, cb, addr); + } + virtual int Recv(void* pv, size_t cb) { + SocketAddress addr; + return RecvFrom(pv, cb, &addr); + } + virtual int RecvFrom(void* pv, size_t cb, SocketAddress* paddr) { + if (type_ == SOCK_DGRAM) { + while (true) { + int res = AsyncSocketAdapter::RecvFrom(pv, cb, paddr); + if (res <= 0) + return res; + if (server_->Check(FP_UDP, *paddr, GetLocalAddress())) + return res; + LOG(LS_VERBOSE) << "FirewallSocket inbound UDP packet from " + << paddr->ToSensitiveString() << " to " + << GetLocalAddress().ToSensitiveString() << " dropped"; + } + } + return AsyncSocketAdapter::RecvFrom(pv, cb, paddr); + } + + virtual int Listen(int backlog) { + if (!server_->tcp_listen_enabled()) { + LOG(LS_VERBOSE) << "FirewallSocket listen attempt denied"; + return -1; + } + + return AsyncSocketAdapter::Listen(backlog); + } + virtual AsyncSocket* Accept(SocketAddress* paddr) { + SocketAddress addr; + while (AsyncSocket* sock = AsyncSocketAdapter::Accept(&addr)) { + if (server_->Check(FP_TCP, addr, GetLocalAddress())) { + if (paddr) + *paddr = addr; + return sock; + } + sock->Close(); + delete sock; + LOG(LS_VERBOSE) << "FirewallSocket inbound TCP connection from " + << addr.ToSensitiveString() << " to " + << GetLocalAddress().ToSensitiveString() << " denied"; + } + return 0; + } + + private: + FirewallSocketServer* server_; + int type_; +}; + +FirewallSocketServer::FirewallSocketServer(SocketServer* server, + FirewallManager* manager, + bool should_delete_server) + : server_(server), manager_(manager), + should_delete_server_(should_delete_server), + udp_sockets_enabled_(true), tcp_sockets_enabled_(true), + tcp_listen_enabled_(true) { + if (manager_) + manager_->AddServer(this); +} + +FirewallSocketServer::~FirewallSocketServer() { + if (manager_) + manager_->RemoveServer(this); + + if (server_ && should_delete_server_) { + delete server_; + server_ = NULL; + } +} + +void FirewallSocketServer::AddRule(bool allow, FirewallProtocol p, + FirewallDirection d, + const SocketAddress& addr) { + SocketAddress src, dst; + if (d == FD_IN) { + dst = addr; + } else { + src = addr; + } + AddRule(allow, p, src, dst); +} + + +void FirewallSocketServer::AddRule(bool allow, FirewallProtocol p, + const SocketAddress& src, + const SocketAddress& dst) { + Rule r; + r.allow = allow; + r.p = p; + r.src = src; + r.dst = dst; + CritScope scope(&crit_); + rules_.push_back(r); +} + +void FirewallSocketServer::ClearRules() { + CritScope scope(&crit_); + rules_.clear(); +} + +bool FirewallSocketServer::Check(FirewallProtocol p, + const SocketAddress& src, + const SocketAddress& dst) { + CritScope scope(&crit_); + for (size_t i = 0; i < rules_.size(); ++i) { + const Rule& r = rules_[i]; + if ((r.p != p) && (r.p != FP_ANY)) + continue; + if ((r.src.ipaddr() != src.ipaddr()) && !r.src.IsNil()) + continue; + if ((r.src.port() != src.port()) && (r.src.port() != 0)) + continue; + if ((r.dst.ipaddr() != dst.ipaddr()) && !r.dst.IsNil()) + continue; + if ((r.dst.port() != dst.port()) && (r.dst.port() != 0)) + continue; + return r.allow; + } + return true; +} + +Socket* FirewallSocketServer::CreateSocket(int type) { + return CreateSocket(AF_INET, type); +} + +Socket* FirewallSocketServer::CreateSocket(int family, int type) { + return WrapSocket(server_->CreateAsyncSocket(family, type), type); +} + +AsyncSocket* FirewallSocketServer::CreateAsyncSocket(int type) { + return CreateAsyncSocket(AF_INET, type); +} + +AsyncSocket* FirewallSocketServer::CreateAsyncSocket(int family, int type) { + return WrapSocket(server_->CreateAsyncSocket(family, type), type); +} + +AsyncSocket* FirewallSocketServer::WrapSocket(AsyncSocket* sock, int type) { + if (!sock || + (type == SOCK_STREAM && !tcp_sockets_enabled_) || + (type == SOCK_DGRAM && !udp_sockets_enabled_)) { + LOG(LS_VERBOSE) << "FirewallSocketServer socket creation denied"; + delete sock; + return NULL; + } + return new FirewallSocket(this, sock, type); +} + +FirewallManager::FirewallManager() { +} + +FirewallManager::~FirewallManager() { + assert(servers_.empty()); +} + +void FirewallManager::AddServer(FirewallSocketServer* server) { + CritScope scope(&crit_); + servers_.push_back(server); +} + +void FirewallManager::RemoveServer(FirewallSocketServer* server) { + CritScope scope(&crit_); + servers_.erase(std::remove(servers_.begin(), servers_.end(), server), + servers_.end()); +} + +void FirewallManager::AddRule(bool allow, FirewallProtocol p, + FirewallDirection d, const SocketAddress& addr) { + CritScope scope(&crit_); + for (std::vector<FirewallSocketServer*>::const_iterator it = + servers_.begin(); it != servers_.end(); ++it) { + (*it)->AddRule(allow, p, d, addr); + } +} + +void FirewallManager::ClearRules() { + CritScope scope(&crit_); + for (std::vector<FirewallSocketServer*>::const_iterator it = + servers_.begin(); it != servers_.end(); ++it) { + (*it)->ClearRules(); + } +} + +} // namespace rtc |