mirror of
https://github.com/pocoproject/poco.git
synced 2025-04-17 15:14:48 +02:00
ICMPSocket does not check reply address #1921
This commit is contained in:
parent
3732c8e13f
commit
f68e0174b6
@ -69,6 +69,9 @@ public:
|
||||
int dataSize() const;
|
||||
/// Returns the data size in bytes.
|
||||
|
||||
int packetSize() const;
|
||||
/// Returns the packet size in bytes.
|
||||
|
||||
int ttl() const;
|
||||
/// Returns the Time-To-Live value.
|
||||
|
||||
|
@ -51,6 +51,9 @@ public:
|
||||
int dataSize() const;
|
||||
/// Returns the data size in bytes.
|
||||
|
||||
int packetSize() const;
|
||||
/// Returns the packet size in bytes.
|
||||
|
||||
int ttl() const;
|
||||
/// Returns the Time-To-Live value.
|
||||
|
||||
@ -70,6 +73,12 @@ private:
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
|
||||
inline int ICMPSocketImpl::packetSize() const
|
||||
{
|
||||
return _icmpPacket.packetSize();
|
||||
}
|
||||
|
||||
inline int ICMPSocketImpl::dataSize() const
|
||||
{
|
||||
return _icmpPacket.getDataSize();
|
||||
|
@ -14,11 +14,10 @@
|
||||
|
||||
#include "Poco/Net/SocketAddress.h"
|
||||
#include "Poco/Net/ICMPClient.h"
|
||||
#include "Poco/Net/ICMPSocket.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Channel.h"
|
||||
#include "Poco/Message.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Format.h"
|
||||
#include <sstream>
|
||||
|
||||
|
||||
@ -62,21 +61,27 @@ int ICMPClient::ping(SocketAddress& address, int repeat) const
|
||||
if (repeat <= 0) return 0;
|
||||
|
||||
ICMPSocket icmpSocket(_family, _dataSize, _ttl, _timeout);
|
||||
SocketAddress returnAddress;
|
||||
|
||||
ICMPEventArgs eventArgs(address, repeat, icmpSocket.dataSize(), icmpSocket.ttl());
|
||||
pingBegin.notify(this, eventArgs);
|
||||
|
||||
for (int i = 0; i < repeat; ++i)
|
||||
{
|
||||
icmpSocket.sendTo(address);
|
||||
++eventArgs;
|
||||
|
||||
try
|
||||
{
|
||||
int t = icmpSocket.receiveFrom(returnAddress);
|
||||
eventArgs.setReplyTime(i, t);
|
||||
pingReply.notify(this, eventArgs);
|
||||
int sent = icmpSocket.sendTo(address);
|
||||
if (icmpSocket.packetSize() == sent)
|
||||
{
|
||||
SocketAddress requestAddress(address);
|
||||
++eventArgs;
|
||||
int t = icmpSocket.receiveFrom(address);
|
||||
poco_assert (address.host() == requestAddress.host());
|
||||
eventArgs.setReplyTime(i, t);
|
||||
pingReply.notify(this, eventArgs);
|
||||
}
|
||||
else
|
||||
throw ICMPException(Poco::format("Error sending ICMP packet "
|
||||
"(sent=%d, expected=%d)", sent, icmpSocket.packetSize()));
|
||||
}
|
||||
catch (TimeoutException&)
|
||||
{
|
||||
@ -89,16 +94,14 @@ int ICMPClient::ping(SocketAddress& address, int repeat) const
|
||||
catch (ICMPException& ex)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << address.host().toString() << ": " << ex.what();
|
||||
os << address.host().toString() << ": " << ex.displayText();
|
||||
eventArgs.setError(i, os.str());
|
||||
pingError.notify(this, eventArgs);
|
||||
continue;
|
||||
}
|
||||
catch (Exception& ex)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << ex.displayText();
|
||||
eventArgs.setError(i, os.str());
|
||||
eventArgs.setError(i, ex.displayText());
|
||||
pingError.notify(this, eventArgs);
|
||||
continue;
|
||||
}
|
||||
@ -125,23 +128,21 @@ int ICMPClient::ping(SocketAddress& address,
|
||||
if (repeat <= 0) return 0;
|
||||
|
||||
ICMPSocket icmpSocket(family, dataSize, ttl, timeout);
|
||||
SocketAddress returnAddress;
|
||||
int received = 0;
|
||||
|
||||
for (int i = 0; i < repeat; ++i)
|
||||
{
|
||||
icmpSocket.sendTo(address);
|
||||
try
|
||||
{
|
||||
icmpSocket.receiveFrom(returnAddress);
|
||||
++received;
|
||||
}
|
||||
catch (TimeoutException&)
|
||||
{
|
||||
}
|
||||
catch (ICMPException&)
|
||||
{
|
||||
SocketAddress requestAddress(address);
|
||||
if (icmpSocket.sendTo(address) == icmpSocket.packetSize())
|
||||
{
|
||||
icmpSocket.receiveFrom(address);
|
||||
poco_assert (address.host() == requestAddress.host());
|
||||
++received;
|
||||
}
|
||||
}
|
||||
catch (Exception&) { }
|
||||
}
|
||||
return received;
|
||||
}
|
||||
|
@ -79,6 +79,12 @@ int ICMPSocket::dataSize() const
|
||||
}
|
||||
|
||||
|
||||
int ICMPSocket::packetSize() const
|
||||
{
|
||||
return static_cast<ICMPSocketImpl*>(impl())->packetSize();
|
||||
}
|
||||
|
||||
|
||||
int ICMPSocket::ttl() const
|
||||
{
|
||||
return static_cast<ICMPSocketImpl*>(impl())->ttl();
|
||||
|
@ -14,9 +14,7 @@
|
||||
|
||||
#include "Poco/Net/ICMPSocketImpl.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Timespan.h"
|
||||
#include "Poco/Timestamp.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Format.h"
|
||||
#include "Poco/Buffer.h"
|
||||
|
||||
|
||||
@ -36,6 +34,7 @@ ICMPSocketImpl::ICMPSocketImpl(IPAddress::Family family, int dataSize, int ttl,
|
||||
_timeout(timeout)
|
||||
{
|
||||
setOption(IPPROTO_IP, IP_TTL, ttl);
|
||||
setBlocking(true);
|
||||
setReceiveTimeout(Timespan(timeout));
|
||||
}
|
||||
|
||||
@ -60,18 +59,40 @@ int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags)
|
||||
try
|
||||
{
|
||||
Poco::Timestamp ts;
|
||||
int rc;
|
||||
int expected = _icmpPacket.packetSize();
|
||||
do
|
||||
{
|
||||
if (ts.isElapsed(_timeout))
|
||||
// guard against a DoS attack
|
||||
if (ts.isElapsed(_timeout)) throw TimeoutException();
|
||||
buffer.clear();
|
||||
SocketAddress respAddr;
|
||||
rc = SocketImpl::receiveFrom(buffer.begin(), expected, respAddr, flags);
|
||||
if (rc == 0) break;
|
||||
if (respAddr == address)
|
||||
{
|
||||
// This guards against a possible DoS attack, where sending
|
||||
// fake ping responses will cause an endless loop.
|
||||
throw TimeoutException();
|
||||
expected -= rc;
|
||||
if (expected == 0)
|
||||
{
|
||||
if (_icmpPacket.validReplyID(buffer.begin(), maxPacketSize)) break;
|
||||
std::string err = _icmpPacket.errorDescription(buffer.begin(), maxPacketSize);
|
||||
if (!err.empty()) throw ICMPException(err);
|
||||
throw ICMPException("Invalid ICMP reply");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ICMPException(Poco::format("Reply from an unknown IP address "
|
||||
"(requested %s, received %s).",
|
||||
address.host().toString(), respAddr.host().toString()));
|
||||
}
|
||||
SocketImpl::receiveFrom(buffer.begin(), maxPacketSize, address, flags);
|
||||
}
|
||||
while (!_icmpPacket.validReplyID(buffer.begin(), maxPacketSize));
|
||||
while (expected && !_icmpPacket.validReplyID(buffer.begin(), maxPacketSize));
|
||||
}
|
||||
catch (ICMPException&)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception&)
|
||||
{
|
||||
std::string err = _icmpPacket.errorDescription(buffer.begin(), maxPacketSize);
|
||||
|
@ -32,6 +32,9 @@ using Poco::Delegate;
|
||||
using Poco::AutoPtr;
|
||||
|
||||
|
||||
Poco::FastMutex ICMPClientTest::_mutex;
|
||||
|
||||
|
||||
ICMPClientTest::ICMPClientTest(const std::string& name):
|
||||
CppUnit::TestCase(name)
|
||||
{
|
||||
@ -60,6 +63,8 @@ void ICMPClientTest::testPing()
|
||||
assert(0 == icmpClient.ping("10.11.12.13"));
|
||||
|
||||
unregisterDelegates(icmpClient);
|
||||
// wait for delegates to finish printing
|
||||
Poco::FastMutex::ScopedLock l(_mutex);
|
||||
}
|
||||
|
||||
|
||||
@ -80,6 +85,8 @@ void ICMPClientTest::testBigPing()
|
||||
assert(0 == icmpClient.ping("10.11.12.13"));
|
||||
|
||||
unregisterDelegates(icmpClient);
|
||||
// wait for delegates to finish printing
|
||||
Poco::FastMutex::ScopedLock l(_mutex);
|
||||
}
|
||||
|
||||
|
||||
@ -113,6 +120,7 @@ void ICMPClientTest::tearDown()
|
||||
|
||||
void ICMPClientTest::onBegin(const void* pSender, ICMPEventArgs& args)
|
||||
{
|
||||
Poco::FastMutex::ScopedLock l(_mutex);
|
||||
std::ostringstream os;
|
||||
os << std::endl << "Pinging " << args.hostName() << " [" << args.hostAddress() << "] with "
|
||||
<< args.dataSize() << " bytes of data:"
|
||||
@ -123,6 +131,7 @@ void ICMPClientTest::onBegin(const void* pSender, ICMPEventArgs& args)
|
||||
|
||||
void ICMPClientTest::onReply(const void* pSender, ICMPEventArgs& args)
|
||||
{
|
||||
Poco::FastMutex::ScopedLock l(_mutex);
|
||||
std::ostringstream os;
|
||||
os << "Reply from " << args.hostAddress()
|
||||
<< " bytes=" << args.dataSize()
|
||||
@ -134,6 +143,7 @@ void ICMPClientTest::onReply(const void* pSender, ICMPEventArgs& args)
|
||||
|
||||
void ICMPClientTest::onError(const void* pSender, ICMPEventArgs& args)
|
||||
{
|
||||
Poco::FastMutex::ScopedLock l(_mutex);
|
||||
std::ostringstream os;
|
||||
os << args.error();
|
||||
std::cerr << os.str() << std::endl;
|
||||
@ -142,6 +152,7 @@ void ICMPClientTest::onError(const void* pSender, ICMPEventArgs& args)
|
||||
|
||||
void ICMPClientTest::onEnd(const void* pSender, ICMPEventArgs& args)
|
||||
{
|
||||
Poco::FastMutex::ScopedLock l(_mutex);
|
||||
std::ostringstream os;
|
||||
int received = args.received();
|
||||
os << std::endl << "--- Ping statistics for " << args.hostAddress() << " ---"
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "Poco/CppUnit/TestCase.h"
|
||||
#include "Poco/Net/ICMPClient.h"
|
||||
#include "Poco/Net/ICMPEventArgs.h"
|
||||
#include "Poco/Mutex.h"
|
||||
|
||||
|
||||
class ICMPClientTest: public CppUnit::TestCase
|
||||
@ -42,6 +43,7 @@ public:
|
||||
private:
|
||||
void registerDelegates(const Poco::Net::ICMPClient& icmpClient);
|
||||
void unregisterDelegates(const Poco::Net::ICMPClient& icmpClient);
|
||||
static Poco::FastMutex _mutex;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user