1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
//
// ICMPSocketImpl.cpp
//
// Library: Net
// Package: ICMP
// Module: ICMPSocketImpl
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Net/ICMPSocketImpl.h"
#include "Poco/Net/NetException.h"
#include "Poco/Timespan.h"
#include "Poco/Timestamp.h"
#include "Poco/Exception.h"
#include "Poco/Buffer.h"
using Poco::TimeoutException;
using Poco::Timespan;
using Poco::Exception;
namespace Poco {
namespace Net {
ICMPSocketImpl::ICMPSocketImpl(IPAddress::Family family, int dataSize, int ttl, int timeout):
RawSocketImpl(family, IPPROTO_ICMP),
_icmpPacket(family, dataSize),
_ttl(ttl),
_timeout(timeout)
{
setOption(IPPROTO_IP, IP_TTL, ttl);
setReceiveTimeout(Timespan(timeout));
}
ICMPSocketImpl::~ICMPSocketImpl()
{
}
int ICMPSocketImpl::sendTo(const void*, int, const SocketAddress& address, int flags)
{
int n = SocketImpl::sendTo(_icmpPacket.packet(), _icmpPacket.packetSize(), address, flags);
return n;
}
int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags)
{
int maxPacketSize = _icmpPacket.maxPacketSize();
Poco::Buffer<unsigned char> buffer(maxPacketSize);
try
{
Poco::Timestamp ts;
do
{
if (ts.isElapsed(_timeout))
{
// This guards against a possible DoS attack, where sending
// fake ping responses will cause an endless loop.
throw TimeoutException();
}
SocketImpl::receiveFrom(buffer.begin(), maxPacketSize, address, flags);
}
while (!_icmpPacket.validReplyID(buffer.begin(), maxPacketSize));
}
catch (TimeoutException&)
{
throw;
}
catch (Exception&)
{
std::string err = _icmpPacket.errorDescription(buffer.begin(), maxPacketSize);
if (!err.empty())
throw ICMPException(err);
else
throw;
}
struct timeval then = _icmpPacket.time(buffer.begin(), maxPacketSize);
struct timeval now = _icmpPacket.time();
int elapsed = (((now.tv_sec * 1000000) + now.tv_usec) - ((then.tv_sec * 1000000) + then.tv_usec))/1000;
return elapsed;
}
} } // namespace Poco::Net
|