]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/icmp/Icmp4.cc
2 * DEBUG: section 42 ICMP Pinger program
3 * AUTHOR: Duane Wessels, Amos Jeffries
5 * SQUID Web Proxy Cache http://www.squid-cache.org/
6 * ----------------------------------------------------------
8 * Squid is the result of efforts by numerous individuals from
9 * the Internet community; see the CONTRIBUTORS file for full
10 * details. Many organizations have provided support for Squid's
11 * development; see the SPONSORS file for full details. Squid is
12 * Copyrighted (C) 2001 by the Regents of the University of
13 * California; see the COPYRIGHT file for full details. Squid
14 * incorporates software developed and/or copyrighted by other
15 * sources; see the CREDITS file for full details.
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
32 //#define SQUID_HELPER 1
40 #include "IcmpPinger.h"
41 #include "leakcheck.h"
42 #include "SquidTime.h"
44 const char *icmpPktStr
[] = {
48 "Destination Unreachable",
65 Icmp4::Icmp4() : Icmp()
78 icmp_sock
= socket(PF_INET
, SOCK_RAW
, IPPROTO_ICMP
);
81 debugs(50, DBG_CRITICAL
, HERE
<< " icmp_sock: " << xstrerror());
85 icmp_ident
= getpid() & 0xffff;
86 debugs(42, DBG_IMPORTANT
, "pinger: ICMP socket opened.");
92 Icmp4::SendEcho(Ip::Address
&to
, int opcode
, const char *payload
, int len
)
95 LOCAL_ARRAY(char, pkt
, MAX_PKT4_SZ
);
97 struct icmphdr
*icmp
= NULL
;
99 size_t icmp_pktsize
= sizeof(struct icmphdr
);
100 struct addrinfo
*S
= NULL
;
102 memset(pkt
, '\0', MAX_PKT4_SZ
);
104 icmp
= (struct icmphdr
*) (void *) pkt
;
107 * cevans - beware signed/unsigned issues in untrusted data from
114 // Construct ICMP packet header
115 icmp
->icmp_type
= ICMP_ECHO
;
117 icmp
->icmp_cksum
= 0;
118 icmp
->icmp_id
= icmp_ident
;
119 icmp
->icmp_seq
= (unsigned short) icmp_pkts_sent
;
122 // Construct ICMP packet data content
123 echo
= (icmpEchoData
*) (icmp
+ 1);
124 echo
->opcode
= (unsigned char) opcode
;
125 memcpy(&echo
->tv
, ¤t_time
, sizeof(struct timeval
));
127 icmp_pktsize
+= sizeof(struct timeval
) + sizeof(char);
130 if (len
> MAX_PAYLOAD
)
133 memcpy(echo
->payload
, payload
, len
);
138 icmp
->icmp_cksum
= CheckSum((unsigned short *) icmp
, icmp_pktsize
);
141 ((sockaddr_in
*)S
->ai_addr
)->sin_port
= 0;
142 assert(icmp_pktsize
<= MAX_PKT4_SZ
);
144 debugs(42, 5, HERE
<< "Send ICMP packet to " << to
<< ".");
146 x
= sendto(icmp_sock
,
154 debugs(42, DBG_IMPORTANT
, HERE
<< "Error sending to ICMP packet to " << to
<< ". ERR: " << xstrerror());
157 Log(to
, ' ', NULL
, 0, 0);
158 Ip::Address::FreeAddrInfo(S
);
165 struct addrinfo
*from
= NULL
;
166 int iphdrlen
= sizeof(iphdr
);
167 struct iphdr
*ip
= NULL
;
168 struct icmphdr
*icmp
= NULL
;
169 static char *pkt
= NULL
;
172 static pingerReplyData preply
;
175 debugs(42, DBG_CRITICAL
, HERE
<< "No socket! Recv() should not be called.");
180 pkt
= (char *)xmalloc(MAX_PKT4_SZ
);
182 Ip::Address::InitAddrInfo(from
);
183 n
= recvfrom(icmp_sock
,
192 #if GETTIMEOFDAY_NO_TZP
198 gettimeofday(&now
, NULL
);
202 debugs(42, 8, HERE
<< n
<< " bytes from " << preply
.from
);
204 ip
= (struct iphdr
*) (void *) pkt
;
206 #if HAVE_STRUCT_IPHDR_IP_HL
208 iphdrlen
= ip
->ip_hl
<< 2;
210 #else /* HAVE_STRUCT_IPHDR_IP_HL */
213 iphdrlen
= (ip
->ip_vhl
>> 4) << 2;
217 iphdrlen
= (ip
->ip_vhl
& 0xF) << 2;
220 #endif /* HAVE_STRUCT_IPHDR_IP_HL */
222 icmp
= (struct icmphdr
*) (void *) (pkt
+ iphdrlen
);
224 if (icmp
->icmp_type
!= ICMP_ECHOREPLY
) {
225 Ip::Address::FreeAddrInfo(from
);
229 if (icmp
->icmp_id
!= icmp_ident
) {
230 Ip::Address::FreeAddrInfo(from
);
234 echo
= (icmpEchoData
*) (void *) (icmp
+ 1);
236 preply
.opcode
= echo
->opcode
;
238 preply
.hops
= ipHops(ip
->ip_ttl
);
241 memcpy(&tv
, &echo
->tv
, sizeof(struct timeval
));
242 preply
.rtt
= tvSubMsec(tv
, now
);
244 preply
.psize
= n
- iphdrlen
- (sizeof(icmpEchoData
) - MAX_PKT4_SZ
);
246 control
.SendResult(preply
, (sizeof(pingerReplyData
) - MAX_PKT4_SZ
+ preply
.psize
) );
248 Log(preply
.from
, icmp
->icmp_type
, icmpPktStr
[icmp
->icmp_type
], preply
.rtt
, preply
.hops
);
249 Ip::Address::FreeAddrInfo(from
);
252 #endif /* USE_ICMP */