26#include <netinet/ip6.h>
35 static const char *icmp6LowPktStr[] = {
37 "Destination Unreachable",
45 return icmp6LowPktStr[(
int)(v&0x7f)];
48 static const char *icmp6HighPktStr[] = {
51 "Multicast Listener Query",
52 "Multicast Listener Report",
53 "Multicast Listener Done",
54 "Router Solicitation",
55 "Router Advertisement",
56 "Neighbor Solicitation",
57 "Neighbor Advertisement",
60 "ICMP Node Information Query",
61 "ICMP Node Information Response",
62 "Inverse Neighbor Discovery Solicitation",
63 "Inverse Neighbor Discovery Advertisement",
64 "Version 2 Multicast Listener Report",
65 "Home Agent Address Discovery Request",
66 "Home Agent Address Discovery Reply",
67 "Mobile Prefix Solicitation",
68 "Mobile Prefix Advertisement",
69 "Certification Path Solicitation",
70 "Certification Path Advertisement",
71 "ICMP Experimental (150)",
72 "Multicast Router Advertisement",
73 "Multicast Router Solicitation",
74 "Multicast Router Termination",
78 if (127 < v && v < 154)
79 return icmp6HighPktStr[(
int)(v&0x7f)];
83 snprintf(buf,
sizeof(buf),
"ICMPv6 %u", v);
122 struct icmp6_hdr *icmp =
nullptr;
124 struct addrinfo *S =
nullptr;
125 size_t icmp6_pktsize = 0;
127 static_assert(
sizeof(*icmp) +
sizeof(*echo) <=
sizeof(pkt),
"our custom ICMPv6 Echo payload fits the packet buffer");
130 icmp = (
struct icmp6_hdr *)pkt;
141 icmp->icmp6_type = ICMP6_ECHO_REQUEST;
142 icmp->icmp6_code = 0;
143 icmp->icmp6_cksum = 0;
148 icmp6_pktsize =
sizeof(
struct icmp6_hdr);
151 echo =
reinterpret_cast<icmpEchoData *
>(
reinterpret_cast<char *
>(pkt) +
sizeof(*icmp));
152 echo->
opcode = (
unsigned char) opcode;
155 icmp6_pktsize +=
sizeof(
struct timeval) + sizeof(char);
161 memcpy(echo->
payload, payload, len);
163 icmp6_pktsize += len;
166 icmp->icmp6_cksum =
CheckSum((
unsigned short *) icmp, icmp6_pktsize);
169 ((sockaddr_in6*)S->ai_addr)->sin6_port = 0;
173 debugs(42, 5,
"Send Icmp6 packet to " << to <<
".");
188 Log(to, 0,
nullptr, 0, 0);
199 struct addrinfo *from =
nullptr;
201 static char *pkt =
nullptr;
202 struct icmp6_hdr *icmp6header =
nullptr;
212 if (pkt ==
nullptr) {
233#if GETTIMEOFDAY_NO_TZP
239 gettimeofday(&
now,
nullptr);
243 debugs(42, 8, n <<
" bytes from " << preply.from);
272 icmp6header = (
struct icmp6_hdr *) pkt;
274 if (icmp6header->icmp6_type != ICMP6_ECHO_REPLY) {
276 switch (icmp6header->icmp6_type) {
284 debugs(42, 8, preply.from <<
" said: " << icmp6header->icmp6_type <<
"/" << (
int)icmp6header->icmp6_code <<
" " <<
292 debugs(42, 8,
"dropping Icmp6 read. IDENT check failed. ident=='" <<
icmp_ident <<
"'=='" << icmp6header->icmp6_id <<
"'");
302 memcpy(&tv, &echo->
tv,
sizeof(
struct timeval));
316 if ( preply.psize > (
unsigned short)
MAX_PKT6_SZ) {
318 }
else if ( preply.psize < (
unsigned short)0) {
323 icmp6header->icmp6_type,
static const char * IcmpPacketType(uint8_t v)
IcmpPinger control
pinger helper contains one of these as a global object.
#define PINGER_PAYLOAD_SZ
int Open() override
Start pinger helper and initiate control channel.
void SendEcho(Ip::Address &, int, const char *, int) override
void SendResult(pingerReplyData &preply, int len)
Send ICMP results back to squid.
virtual void Close()
Shutdown pinger helper and control channel.
int CheckSum(unsigned short *ptr, int size)
Calculate a packet checksum.
void Log(const Ip::Address &addr, const uint8_t type, const char *pkt_str, const int rtt, const int hops)
Log the packet.
static void InitAddr(struct addrinfo *&ai)
static void FreeAddr(struct addrinfo *&ai)
void getAddrInfo(struct addrinfo *&ai, int force=AF_UNSPEC) const
#define debugs(SECTION, LEVEL, CONTENT)
#define LOCAL_ARRAY(type, name, size)
char payload[MAX_PAYLOAD]
struct timeval current_time
the current UNIX time in timeval {seconds, microseconds} format
int tvSubMsec(struct timeval t1, struct timeval t2)
const char * xstrerr(int error)