I try to connect to socket to send icmp echo request with modified boost/pinger.cpp return
Operation not permitted
even I am root user.
In Ubuntu 20.04, I am runnig the program with sudo there is no problem it works. But if I run at ARM with poky OS (Yocto) (with root of course) it return the error as I said.
Error occured when I try to
mSocket.async_connect(mDestination, boost::bind(&Pinger::startSend, this, boost::placeholders::_1));
Here is my code
pinger.cpp
#include "pinger.h"
Pinger::Pinger(boost::asio::io_context &io_context, const char *destination)
: mResolver(io_context), mSocket(io_context),
mTimeoutTimer(io_context), mSequenceNumber(1)
{
mDestination = *mResolver.resolve(boost::asio::ip::icmp::v4(), destination, "");
}
void Pinger::start()
{
startConnect();
}
void Pinger::stop()
{
mSocket.close();
mTimeoutTimer.cancel();
}
void Pinger::startConnect()
{
mSocket.async_connect(mDestination, boost::bind(&Pinger::startSend, this, boost::placeholders::_1));
}
void Pinger::startSend(const boost::system::error_code &ec)
{
if (ec)
return;
std::string body("\"Hello!\" from pinger.");
// Create an ICMP header for an echo request.
icmp_header echo_request;
echo_request.type(icmp_header::echo_request);
echo_request.code(0);
echo_request.identifier(getIdentifier());
echo_request.sequence_number(mSequenceNumber);
compute_checksum(echo_request, body.begin(), body.end());
// Encode the request packet.
boost::asio::streambuf request_buffer;
std::ostream os(&request_buffer);
os << echo_request << body;
// Send the request.
mTimeSent = boost::asio::steady_timer::clock_type::now();
mSocket.async_send(request_buffer.data(), boost::bind(&Pinger::startReceive, this, boost::placeholders::_1));
// Wait up to ten seconds for a reply.
mTimeoutTimer.expires_at(mTimeSent + boost::asio::chrono::seconds(15));
mTimeoutTimer.async_wait(boost::bind(&Pinger::handleTimeout, this, boost::placeholders::_1));
}
void Pinger::startReceive(const boost::system::error_code &ec)
{
if (ec)
return;
// Discard any data already in the buffer.
mReplyBuffer.consume(mReplyBuffer.size());
// Wait for a reply. We prepare the buffer to receive up to 64KB.
mSocket.async_receive(mReplyBuffer.prepare(65536),
boost::bind(&Pinger::handleReceive, this, boost::placeholders::_1, _2));
}
void Pinger::handleReceive(const boost::system::error_code &ec, std::size_t length)
{
if (ec)
return;
// The actual number of bytes received is committed to the buffer so that we
// can extract it using a std::istream object.
mReplyBuffer.commit(length);
// Decode the reply packet.
std::istream is(&mReplyBuffer);
ipv4_header ipv4_hdr;
icmp_header icmp_hdr;
is >> ipv4_hdr >> icmp_hdr;
// We can receive all ICMP packets received by the host, so we need to
// filter that match the our identifier.
if (is && icmp_hdr.identifier() == getIdentifier() && icmp_hdr.sequence_number() == mSequenceNumber)
{
if (!mResultSent)
{
mResultSent = true;
stop();
onResult(true);
return;
}
}
}
void Pinger::handleTimeout(const boost::system::error_code &ec)
{
if (ec == boost::asio::error::operation_aborted)
return;
if (!mResultSent)
{
mResultSent = true;
stop();
onResult(false);
}
}
unsigned short Pinger::getIdentifier()
{
#if defined(BOOST_ASIO_WINDOWS)
return static_cast<unsigned short>(::GetCurrentProcessId());
#else
return static_cast<unsigned short>(::getpid());
#endif
}
pinger.h
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/signals2.hpp>
#include <istream>
#include <iostream>
#include <ostream>
#include "icmp_header.hpp"
#include "ipv4_header.hpp"
class Pinger
{
public:
Pinger(boost::asio::io_context &io_context, const char *destination);
void start();
void stop();
//signals
boost::signals2::signal<void(bool isAlive)> onResult;
private:
void startConnect();
void startSend(const boost::system::error_code &ec);
void startReceive(const boost::system::error_code &ec);
void handleReceive(const boost::system::error_code &ec, std::size_t length);
void handleTimeout(const boost::system::error_code &ec);
static unsigned short getIdentifier();
boost::asio::ip::icmp::resolver mResolver;
boost::asio::ip::icmp::endpoint mDestination;
boost::asio::ip::icmp::socket mSocket;
boost::asio::steady_timer mTimeoutTimer;
unsigned short mSequenceNumber;
boost::asio::chrono::steady_clock::time_point mTimeSent;
boost::asio::streambuf mReplyBuffer;
bool mResultSent = false;
};