Go to the documentation of this file.
27 #if HAVE_NETINET_IP6_H
28 #include <netinet/ip6.h>
37 static const char *icmp6LowPktStr[] = {
39 "Destination Unreachable",
47 return icmp6LowPktStr[(
int)(v&0x7f)];
50 static const char *icmp6HighPktStr[] = {
53 "Multicast Listener Query",
54 "Multicast Listener Report",
55 "Multicast Listener Done",
56 "Router Solicitation",
57 "Router Advertisement",
58 "Neighbor Solicitation",
59 "Neighbor Advertisement",
62 "ICMP Node Information Query",
63 "ICMP Node Information Response",
64 "Inverse Neighbor Discovery Solicitation",
65 "Inverse Neighbor Discovery Advertisement",
66 "Version 2 Multicast Listener Report",
67 "Home Agent Address Discovery Request",
68 "Home Agent Address Discovery Reply",
69 "Mobile Prefix Solicitation",
70 "Mobile Prefix Advertisement",
71 "Certification Path Solicitation",
72 "Certification Path Advertisement",
73 "ICMP Experimental (150)",
74 "Multicast Router Advertisement",
75 "Multicast Router Solicitation",
76 "Multicast Router Termination",
80 if (127 < v && v < 154)
81 return icmp6HighPktStr[(
int)(v&0x7f)];
85 snprintf(buf,
sizeof(buf),
"ICMPv6 %u", v);
124 struct icmp6_hdr *icmp =
nullptr;
126 struct addrinfo *S =
nullptr;
127 size_t icmp6_pktsize = 0;
129 static_assert(
sizeof(*icmp) +
sizeof(*echo) <=
sizeof(pkt),
"our custom ICMPv6 Echo payload fits the packet buffer");
132 icmp = (
struct icmp6_hdr *)pkt;
143 icmp->icmp6_type = ICMP6_ECHO_REQUEST;
144 icmp->icmp6_code = 0;
145 icmp->icmp6_cksum = 0;
150 icmp6_pktsize =
sizeof(
struct icmp6_hdr);
153 echo =
reinterpret_cast<icmpEchoData *
>(
reinterpret_cast<char *
>(pkt) +
sizeof(*icmp));
154 echo->
opcode = (
unsigned char) opcode;
157 icmp6_pktsize +=
sizeof(
struct timeval) + sizeof(char);
163 memcpy(echo->
payload, payload, len);
165 icmp6_pktsize += len;
168 icmp->icmp6_cksum =
CheckSum((
unsigned short *) icmp, icmp6_pktsize);
173 ((sockaddr_in6*)S->ai_addr)->sin6_port = 0;
177 debugs(42, 5,
"Send Icmp6 packet to " << to <<
".");
192 Log(to, 0,
"", 0, 0);
203 struct addrinfo *from =
nullptr;
205 static char *pkt =
nullptr;
206 struct icmp6_hdr *icmp6header =
nullptr;
216 if (pkt ==
nullptr) {
234 if (n <
static_cast<int>(
sizeof(
struct icmp6_hdr))) {
241 #if GETTIMEOFDAY_NO_TZP
247 gettimeofday(&now,
nullptr);
251 debugs(42, 8, n <<
" bytes from " << preply.from);
280 icmp6header = (
struct icmp6_hdr *) pkt;
282 if (icmp6header->icmp6_type != ICMP6_ECHO_REPLY) {
284 switch (icmp6header->icmp6_type) {
292 debugs(42, 8, preply.from <<
" said: " << icmp6header->icmp6_type <<
"/" << (
int)icmp6header->icmp6_code <<
" " <<
299 if (ntohs(icmp6header->icmp6_id) !=
static_cast<uint16_t
>(
icmp_ident)) {
300 debugs(42, 8,
"dropping Icmp6 read. IDENT check failed. ident=='" <<
icmp_ident <<
"'=='" << icmp6header->icmp6_id <<
"'");
305 const auto meta =
static_cast<int>(
sizeof(
struct icmp6_hdr) + sizeof(struct timeval) + sizeof(unsigned char));
310 echo = (
icmpEchoData *)(pkt +
sizeof(
struct icmp6_hdr));
315 memcpy(&tv, &echo->
tv,
sizeof(
struct timeval));
326 auto payload_len = n - meta;
331 preply.psize = payload_len;
332 if (preply.psize > 0) {
333 memcpy(preply.payload, echo->
payload, preply.psize);
337 icmp6header->icmp6_type,
const char * xstrerr(int error)
#define LOCAL_ARRAY(type, name, size)
#define PINGER_PAYLOAD_SZ
IcmpPinger control
pinger helper contains one of these as a global object.
int Open() override
Start pinger helper and initiate control channel.
static void FreeAddr(struct addrinfo *&ai)
virtual void Close()
Shutdown pinger helper and control channel.
int tvSubMsec(struct timeval t1, struct timeval t2)
ssize_t xrecvfrom(int socketFd, void *buf, size_t bufLength, int flags, struct sockaddr *from, socklen_t *fromLength)
POSIX recvfrom(2) equivalent.
struct timeval current_time
the current UNIX time in timeval {seconds, microseconds} format
void SendEcho(Ip::Address &, int, const char *, int) override
char payload[MAX_PAYLOAD]
static const char * IcmpPacketType(uint8_t v)
#define Assure(condition)
int xsocket(int domain, int type, int protocol)
POSIX socket(2) equivalent.
void getAddrInfo(struct addrinfo *&ai, int force=AF_UNSPEC) const
void SendResult(pingerReplyData &preply, int len)
Send ICMP results back to squid.
ssize_t xsendto(int socketFd, const void *buf, size_t bufLength, int flags, const struct sockaddr *to, socklen_t toLength)
POSIX sendto(2) equivalent.
int CheckSum(unsigned short *ptr, int size)
Calculate a packet checksum.
#define debugs(SECTION, LEVEL, CONTENT)
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)