]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/icmp/Icmp4.cc
2 * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
9 /* DEBUG: section 42 ICMP Pinger program */
11 //#define SQUID_HELPER 1
19 #include "IcmpPinger.h"
20 #include "leakcheck.h"
21 #include "SquidTime.h"
24 IcmpPacketType(uint8_t v
)
26 static const char *icmpPktStr
[] = {
30 "Destination Unreachable",
49 snprintf(buf
, sizeof(buf
), "ICMP %u (invalid)", v
);
56 Icmp4::Icmp4() : Icmp()
69 icmp_sock
= socket(PF_INET
, SOCK_RAW
, IPPROTO_ICMP
);
73 debugs(50, DBG_CRITICAL
, MYNAME
<< " icmp_sock: " << xstrerr(xerrno
));
77 icmp_ident
= getpid() & 0xffff;
78 debugs(42, DBG_IMPORTANT
, "pinger: ICMP socket opened.");
84 Icmp4::SendEcho(Ip::Address
&to
, int opcode
, const char *payload
, int len
)
87 LOCAL_ARRAY(char, pkt
, MAX_PKT4_SZ
);
89 struct icmphdr
*icmp
= NULL
;
91 size_t icmp_pktsize
= sizeof(struct icmphdr
);
92 struct addrinfo
*S
= NULL
;
94 memset(pkt
, '\0', MAX_PKT4_SZ
);
96 icmp
= (struct icmphdr
*) (void *) pkt
;
99 * cevans - beware signed/unsigned issues in untrusted data from
106 // Construct ICMP packet header
107 icmp
->icmp_type
= ICMP_ECHO
;
109 icmp
->icmp_cksum
= 0;
110 icmp
->icmp_id
= icmp_ident
;
111 icmp
->icmp_seq
= (unsigned short) icmp_pkts_sent
;
114 // Construct ICMP packet data content
115 echo
= (icmpEchoData
*) (icmp
+ 1);
116 echo
->opcode
= (unsigned char) opcode
;
117 memcpy(&echo
->tv
, ¤t_time
, sizeof(struct timeval
));
119 icmp_pktsize
+= sizeof(struct timeval
) + sizeof(char);
122 if (len
> MAX_PAYLOAD
)
125 memcpy(echo
->payload
, payload
, len
);
130 icmp
->icmp_cksum
= CheckSum((unsigned short *) icmp
, icmp_pktsize
);
133 ((sockaddr_in
*)S
->ai_addr
)->sin_port
= 0;
134 assert(icmp_pktsize
<= MAX_PKT4_SZ
);
136 debugs(42, 5, HERE
<< "Send ICMP packet to " << to
<< ".");
138 x
= sendto(icmp_sock
,
147 debugs(42, DBG_IMPORTANT
, MYNAME
<< "ERROR: sending to ICMP packet to " << to
<< ": " << xstrerr(xerrno
));
150 Log(to
, ' ', NULL
, 0, 0);
151 Ip::Address::FreeAddr(S
);
158 struct addrinfo
*from
= NULL
;
159 int iphdrlen
= sizeof(iphdr
);
160 struct iphdr
*ip
= NULL
;
161 struct icmphdr
*icmp
= NULL
;
162 static char *pkt
= NULL
;
165 static pingerReplyData preply
;
168 debugs(42, DBG_CRITICAL
, HERE
<< "No socket! Recv() should not be called.");
173 pkt
= (char *)xmalloc(MAX_PKT4_SZ
);
175 Ip::Address::InitAddr(from
);
176 n
= recvfrom(icmp_sock
,
184 debugs(42, DBG_CRITICAL
, HERE
<< "Error when calling recvfrom() on ICMP socket.");
185 Ip::Address::FreeAddr(from
);
191 #if GETTIMEOFDAY_NO_TZP
197 gettimeofday(&now
, NULL
);
201 debugs(42, 8, HERE
<< n
<< " bytes from " << preply
.from
);
203 ip
= (struct iphdr
*) (void *) pkt
;
205 #if HAVE_STRUCT_IPHDR_IP_HL
207 iphdrlen
= ip
->ip_hl
<< 2;
209 #else /* HAVE_STRUCT_IPHDR_IP_HL */
212 iphdrlen
= (ip
->ip_vhl
>> 4) << 2;
216 iphdrlen
= (ip
->ip_vhl
& 0xF) << 2;
219 #endif /* HAVE_STRUCT_IPHDR_IP_HL */
221 icmp
= (struct icmphdr
*) (void *) (pkt
+ iphdrlen
);
223 if (icmp
->icmp_type
!= ICMP_ECHOREPLY
) {
224 Ip::Address::FreeAddr(from
);
228 if (icmp
->icmp_id
!= icmp_ident
) {
229 Ip::Address::FreeAddr(from
);
233 echo
= (icmpEchoData
*) (void *) (icmp
+ 1);
235 preply
.opcode
= echo
->opcode
;
237 preply
.hops
= ipHops(ip
->ip_ttl
);
240 memcpy(&tv
, &echo
->tv
, sizeof(struct timeval
));
241 preply
.rtt
= tvSubMsec(tv
, now
);
243 preply
.psize
= n
- iphdrlen
- (sizeof(icmpEchoData
) - MAX_PKT4_SZ
);
245 if (preply
.psize
< 0) {
246 debugs(42, DBG_CRITICAL
, HERE
<< "Malformed ICMP packet.");
247 Ip::Address::FreeAddr(from
);
251 control
.SendResult(preply
, (sizeof(pingerReplyData
) - MAX_PKT4_SZ
+ preply
.psize
) );
253 Log(preply
.from
, icmp
->icmp_type
, IcmpPacketType(icmp
->icmp_type
), preply
.rtt
, preply
.hops
);
254 Ip::Address::FreeAddr(from
);
257 #endif /* USE_ICMP */