The sendto() and recvfrom() functions in the C++ code I wrote to ping IPV6 using icmpv6 via socket layer always return a value of 64, regardless of whether the IPV6 address is reachable or not.
Need someone assistance in figuring out what went wrong and how to fix it?
Code logic:
#include <iostream>
#ifdef UNIX
#include <sys/socket.h>
#ifdef PLATFORM_OSX
#include <netinet/ip.h>
#else
#include <netinet/in.h>
#endif
#include <net/if.h>
#include <netinet/ip_icmp.h>
#include <netinet/icmp6.h>
#include <arpa/inet.h>
#define PACKET_SIZE 64
class CPingCommandIPV6
{
CPingCommandIPV6(const std::string& hostname, int timeout) :
m_Timeout(timeout),
m_Hostname(hostname)
{
m_Socket = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
if (m_Socket < 0)
{
LOG_ERROR("Ping: failed to create socket IPV6 - %s", strerror(errno));
return false;
}
LOG_INFO("Socket Creation Successful for IPV6 :: %s", m_Hostname.c_str());
//Set TTL(Time to Live)
m_Ttl = 64;
setsockopt(m_Socket, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &m_Ttl, sizeof(m_Ttl));
memset(&m_To, 0, sizeof(m_To));
m_To.sin6_family = AF_INET6;
//m_To.sin6_addr = in6addr_any;
inet_pton(AF_INET6, m_Hostname.c_str(), &m_To.sin6_addr)
// Prepare ICMPv6 echo request packet
struct icmp6_hdr *pIcmpPacket = (struct icmp6_hdr*)m_RequestPacket;
//Initialize ICMPV6 header
pIcmpPacket->icmp6_type = ICMP6_ECHO_REQUEST;
pIcmpPacket->icmp6_code = 0;
pIcmpPacket->icmp6_cksum = 0;
pIcmpPacket->icmp6_seq = htons(0); /* seq and id must be reflected */
pIcmpPacket->icmp6_id = htons(getpid());
memset(m_RequestPacket + sizeof(struct icmp6_hdr), 0, PACKET_SIZE - sizeof(struct icmp6_hdr));
LOG_INFO("Packet initialization part for IPV6");
pIcmpPacket->icmp6_cksum = checksum(m_RequestPacket, PACKET_SIZE);
}
public:
bool RunIPV6();
private:
int m_Timeout;
int m_Socket;
int m_Ttl;
std::string m_Hostname;
struct sockaddr_in6 m_To;
uint8_t m_RequestPacket[PACKET_SIZE];
uint8_t m_ReplyPacket[PACKET_SIZE];
};
CPingCommandIPV6::CPingCommandIPV6(const std::string& hostname, int timeout)
: m(std::make_unique<CPingCommandIPV6::Impl>(hostname, timeout))
{
}
CPingCommandIPV6::~CPingCommandIPV6()
{
close(m_Socket);
}
bool CPingCommandIPV6::RunIPV6()
{
LOG_INFO("PingCommand Before sending - IPV6");
int sent = sendto(m_Socket, m_RequestPacket, PACKET_SIZE, 0, (struct sockaddr*)&m_To, (socklen_t)sizeof(struct sockaddr_in6));
LOG_INFO("PingCommand After sending - IPV6 :: %d", sent);
if (sent <= 0)
{
LOG_INFO("PingCommand Request not sent IPV6 :: %d", sent);
return false;
}
else
{
LOG_INFO("Ping command request sent properly :: %d", sent);
}
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(m_Socket, &rfds);
struct timeval tv;
tv.tv_sec = m_Timeout / 1000;
tv.tv_usec = (m_Timeout % 1000) * 1000;
bool cont = true;
while (cont)
{
LOG_INFO("Listen for replies1 - IPV6");
int retval = select(m_Socket + 1, &rfds, NULL, NULL, &tv);
if (retval == -1)
{
LOG_INFO("Listen for replies2 - IPV6");
return false;
}
else if (retval == 0)
{
// timeout
LOG_INFO("Listen for replies3 - IPV6");
return false;
}
else
{
LOG_INFO("Listen for replies4 - IPV6");
//Receive ICMPV6 response
struct sockaddr_in6 from;
socklen_t fromlen = sizeof(from);
LOG_INFO("PingCommand Before Receive from -IPV6");
int ret = recvfrom(m_Socket, (char*)m_ReplyPacket, PACKET_SIZE, 0, (sockaddr*)&from, &fromlen);
LOG_INFO("PingCommand After Receiving from - IPV6 :: %d", ret);
if (ret <= 0)
{
LOG_INFO("PingCommand not received from - IPV6 :: %d", ret);
return false;
}
else
{
//LOG_INFO("Received ICMPV6 response from:: %s",inet_ntop(AF_INET6, &from.sin6_addr,(char*)m_ReplyPacket, sizeof(m_ReplyPacket)));
LOG_INFO("RunIPV6() returns true successfully- IPV6 :: %d", ret);
return true;
}
}
}
}
int main()
{
static uint32_t kTimeout = 1000;
std::string m_ipv6Address = "1050:0000:0000:0000:0005:0600:300c:326b";
CPingCommandIPV6 PingIPV6(m_IpAddress, kTimeout);
//To check physical connection
if (PingIPV6.RunIPV6())
{
LOG_DEBUG("IPV6 Ping successful");
}
else
{
LOG_DEBUG("Time out - IPV6");
}
return 0;
}
#endif
Expectation:
- Ping IPv6 address if the address is reachable and return true for RunIPV6() else return false.
- But In my case, it always return true regardless of IPV6 Address is reachable or not. Because sendto() api always returns 64 in both the successful and not successful cases.
I expect the code should return <=0 if ipv6 address are not reachable.