]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/icmp/Icmp4.cc
2 * Copyright (C) 1996-2014 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
);
72 debugs(50, DBG_CRITICAL
, HERE
<< " icmp_sock: " << xstrerror());
76 icmp_ident
= getpid() & 0xffff;
77 debugs(42, DBG_IMPORTANT
, "pinger: ICMP socket opened.");
83 Icmp4::SendEcho(Ip::Address
&to
, int opcode
, const char *payload
, int len
)
86 LOCAL_ARRAY(char, pkt
, MAX_PKT4_SZ
);
88 struct icmphdr
*icmp
= NULL
;
90 size_t icmp_pktsize
= sizeof(struct icmphdr
);
91 struct addrinfo
*S
= NULL
;
93 memset(pkt
, '\0', MAX_PKT4_SZ
);
95 icmp
= (struct icmphdr
*) (void *) pkt
;
98 * cevans - beware signed/unsigned issues in untrusted data from
105 // Construct ICMP packet header
106 icmp
->icmp_type
= ICMP_ECHO
;
108 icmp
->icmp_cksum
= 0;
109 icmp
->icmp_id
= icmp_ident
;
110 icmp
->icmp_seq
= (unsigned short) icmp_pkts_sent
;
113 // Construct ICMP packet data content
114 echo
= (icmpEchoData
*) (icmp
+ 1);
115 echo
->opcode
= (unsigned char) opcode
;
116 memcpy(&echo
->tv
, ¤t_time
, sizeof(struct timeval
));
118 icmp_pktsize
+= sizeof(struct timeval
) + sizeof(char);
121 if (len
> MAX_PAYLOAD
)
124 memcpy(echo
->payload
, payload
, len
);
129 icmp
->icmp_cksum
= CheckSum((unsigned short *) icmp
, icmp_pktsize
);
132 ((sockaddr_in
*)S
->ai_addr
)->sin_port
= 0;
133 assert(icmp_pktsize
<= MAX_PKT4_SZ
);
135 debugs(42, 5, HERE
<< "Send ICMP packet to " << to
<< ".");
137 x
= sendto(icmp_sock
,
145 debugs(42, DBG_IMPORTANT
, HERE
<< "Error sending to ICMP packet to " << to
<< ". ERR: " << xstrerror());
148 Log(to
, ' ', NULL
, 0, 0);
149 Ip::Address::FreeAddr(S
);
156 struct addrinfo
*from
= NULL
;
157 int iphdrlen
= sizeof(iphdr
);
158 struct iphdr
*ip
= NULL
;
159 struct icmphdr
*icmp
= NULL
;
160 static char *pkt
= NULL
;
163 static pingerReplyData preply
;
166 debugs(42, DBG_CRITICAL
, HERE
<< "No socket! Recv() should not be called.");
171 pkt
= (char *)xmalloc(MAX_PKT4_SZ
);
173 Ip::Address::InitAddr(from
);
174 n
= recvfrom(icmp_sock
,
182 debugs(42, DBG_CRITICAL
, HERE
<< "Error when calling recvfrom() on ICMP socket.");
183 Ip::Address::FreeAddr(from
);
189 #if GETTIMEOFDAY_NO_TZP
195 gettimeofday(&now
, NULL
);
199 debugs(42, 8, HERE
<< n
<< " bytes from " << preply
.from
);
201 ip
= (struct iphdr
*) (void *) pkt
;
203 #if HAVE_STRUCT_IPHDR_IP_HL
205 iphdrlen
= ip
->ip_hl
<< 2;
207 #else /* HAVE_STRUCT_IPHDR_IP_HL */
210 iphdrlen
= (ip
->ip_vhl
>> 4) << 2;
214 iphdrlen
= (ip
->ip_vhl
& 0xF) << 2;
217 #endif /* HAVE_STRUCT_IPHDR_IP_HL */
219 icmp
= (struct icmphdr
*) (void *) (pkt
+ iphdrlen
);
221 if (icmp
->icmp_type
!= ICMP_ECHOREPLY
) {
222 Ip::Address::FreeAddr(from
);
226 if (icmp
->icmp_id
!= icmp_ident
) {
227 Ip::Address::FreeAddr(from
);
231 echo
= (icmpEchoData
*) (void *) (icmp
+ 1);
233 preply
.opcode
= echo
->opcode
;
235 preply
.hops
= ipHops(ip
->ip_ttl
);
238 memcpy(&tv
, &echo
->tv
, sizeof(struct timeval
));
239 preply
.rtt
= tvSubMsec(tv
, now
);
241 preply
.psize
= n
- iphdrlen
- (sizeof(icmpEchoData
) - MAX_PKT4_SZ
);
243 if (preply
.psize
< 0) {
244 debugs(42, DBG_CRITICAL
, HERE
<< "Malformed ICMP packet.");
245 Ip::Address::FreeAddr(from
);
249 control
.SendResult(preply
, (sizeof(pingerReplyData
) - MAX_PKT4_SZ
+ preply
.psize
) );
251 Log(preply
.from
, icmp
->icmp_type
, IcmpPacketType(icmp
->icmp_type
), preply
.rtt
, preply
.hops
);
252 Ip::Address::FreeAddr(from
);
255 #endif /* USE_ICMP */