My goal is to write a little program in c++ with boost asio that notifies me whenever an ICMP packet is received on any network interface.
The program doesn't print any errors and there are no exceptions.
But it also doesn't receive any ICMP packets sent by any program but one (the ping example of boost asio, which can be found here).
What's even stranger is the fact that the ICMP echo request packet from the boost example (after adjusting the payload and the ICMP identifier accordingly) and the default windows ICMP echo request (when using "ping" in the windows commmand line) look almost exactly the same in wireshark. The only difference beeing the identification field in the IPv4 header and thus also the ICMP checksum.
The same behaviour can be observed no matter where the echo request comes from, be it a virtual machine or another real computer in the network. I can ping all those machines without any issues.
Disabling the windows firewall yields the same result.
OS: Windows 10 64 bit Enterprise N (10.0.10586 Build 10586)
Boost version: 1.62.0.
IDE: Microsoft Visual Studio Community 15.
Here is what I came up with:
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/icmp.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/placeholders.hpp>
#include <boost/system/error_code.hpp>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <iostream>
class ICMPReceiver {
public:
ICMPReceiver( boost::asio::io_service & IOS ):
m_sock( IOS ),
m_localEP( boost::asio::ip::icmp::v4(), 0 )
{
}
bool open() {
boost::system::error_code ec;
if ( !m_sock.is_open() ) {
m_sock.open( boost::asio::ip::icmp::v4(), ec );
if ( ec ) {
std::cerr << "Error in socket.open():\n" << ec.message() << '\n';
return false;
}
}
return true;
}
bool bind() {
boost::system::error_code ec;
m_sock.bind( m_localEP, ec );
if ( ec ) {
std::cerr << "Error in socket.bind():\n" << ec.message() << '\n';
return false;
}
}
bool startReceiving() {
try {
m_sock.async_receive_from( boost::asio::buffer( m_receiveBuffer ),
m_remoteEP,
boost::bind( &ICMPReceiver::receiveHandle,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred ) );
} catch ( std::exception const & e ) {
std::cerr << "Exception in socket.async_receive_from():\n" << e.what() << '\n';
return false;
}
return true;
}
private:
void receiveHandle( boost::system::error_code const & ec, size_t bytes ) {
if ( ec ) {
if ( ec != boost::asio::error::operation_aborted ) {
std::cerr << "Error in receiveHandle():\n" << "Code: " << ec << ": " << ec.message() << '\n';
return;
} else {
std::cerr << "operation aborted\n";
return;
}
} else {
std::cout << "ICMP packet received\n";
}
startReceiving();
}
boost::asio::ip::icmp::socket m_sock;
boost::asio::ip::icmp::endpoint m_localEP;
boost::asio::ip::icmp::endpoint m_remoteEP;
boost::array< char, 2048 > m_receiveBuffer;
};
int main() {
try {
boost::asio::io_service IOS;
ICMPReceiver receiver( IOS );
receiver.open();
receiver.bind();
receiver.startReceiving();
IOS.run();
return 0;
} catch ( std::exception const & e ) {
std::cerr << "Unhandled exception: " << e.what() << '\n';
return 1;
}
}