]> git.ipfire.org Git - thirdparty/squid.git/blame - src/icmp/Icmp4.cc
Prepare external_acl_type format codes for libformat upgrade
[thirdparty/squid.git] / src / icmp / Icmp4.cc
CommitLineData
cc192b50 1/*
cc192b50 2 * DEBUG: section 42 ICMP Pinger program
3 * AUTHOR: Duane Wessels, Amos Jeffries
4 *
5 * SQUID Web Proxy Cache http://www.squid-cache.org/
6 * ----------------------------------------------------------
7 *
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.
16 *
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.
26ac0430 21 *
cc192b50 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.
26ac0430 26 *
cc192b50 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.
30 *
31 */
32//#define SQUID_HELPER 1
33
582c2af2 34#include "squid.h"
cc192b50 35
36#if USE_ICMP
37
582c2af2 38#include "leakcheck.h"
cc192b50 39#include "SquidTime.h"
b826ffb5
AJ
40#include "Icmp4.h"
41#include "IcmpPinger.h"
cc192b50 42#include "Debug.h"
43
26ac0430
AJ
44const char *icmpPktStr[] = {
45 "Echo Reply",
46 "ICMP 1",
47 "ICMP 2",
48 "Destination Unreachable",
49 "Source Quench",
50 "Redirect",
51 "ICMP 6",
52 "ICMP 7",
53 "Echo",
54 "ICMP 9",
55 "ICMP 10",
56 "Time Exceeded",
57 "Parameter Problem",
58 "Timestamp",
59 "Timestamp Reply",
60 "Info Request",
61 "Info Reply",
62 "Out of Range Type"
63};
cc192b50 64
b826ffb5 65Icmp4::Icmp4() : Icmp()
26ac0430
AJ
66{
67 ;
cc192b50 68}
69
b826ffb5 70Icmp4::~Icmp4()
cc192b50 71{
72 Close();
73}
74
75int
b826ffb5 76Icmp4::Open(void)
cc192b50 77{
78 icmp_sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
79
80 if (icmp_sock < 0) {
fa84c01d 81 debugs(50, DBG_CRITICAL, HERE << " icmp_sock: " << xstrerror());
cc192b50 82 return -1;
83 }
84
85 icmp_ident = getpid() & 0xffff;
e0236918 86 debugs(42, DBG_IMPORTANT, "pinger: ICMP socket opened.");
cc192b50 87
88 return icmp_sock;
89}
90
91void
b7ac5457 92Icmp4::SendEcho(Ip::Address &to, int opcode, const char *payload, int len)
cc192b50 93{
94 int x;
95 LOCAL_ARRAY(char, pkt, MAX_PKT4_SZ);
96
97 struct icmphdr *icmp = NULL;
98 icmpEchoData *echo;
99 size_t icmp_pktsize = sizeof(struct icmphdr);
100 struct addrinfo *S = NULL;
101
102 memset(pkt, '\0', MAX_PKT4_SZ);
103
104 icmp = (struct icmphdr *) (void *) pkt;
105
106 /*
107 * cevans - beware signed/unsigned issues in untrusted data from
108 * the network!!
109 */
26ac0430 110 if (len < 0) {
cc192b50 111 len = 0;
112 }
113
114 // Construct ICMP packet header
115 icmp->icmp_type = ICMP_ECHO;
116 icmp->icmp_code = 0;
117 icmp->icmp_cksum = 0;
118 icmp->icmp_id = icmp_ident;
aec55359
FC
119 icmp->icmp_seq = (unsigned short) icmp_pkts_sent;
120 ++icmp_pkts_sent;
cc192b50 121
122 // Construct ICMP packet data content
123 echo = (icmpEchoData *) (icmp + 1);
124 echo->opcode = (unsigned char) opcode;
c3c6695b 125 memcpy(&echo->tv, &current_time, sizeof(struct timeval));
cc192b50 126
127 icmp_pktsize += sizeof(struct timeval) + sizeof(char);
128
26ac0430 129 if (payload) {
cc192b50 130 if (len > MAX_PAYLOAD)
131 len = MAX_PAYLOAD;
132
41d00cd3 133 memcpy(echo->payload, payload, len);
cc192b50 134
135 icmp_pktsize += len;
136 }
137
f45dd259 138 icmp->icmp_cksum = CheckSum((unsigned short *) icmp, icmp_pktsize);
cc192b50 139
140 to.GetAddrInfo(S);
141 ((sockaddr_in*)S->ai_addr)->sin_port = 0;
142 assert(icmp_pktsize <= MAX_PKT4_SZ);
143
30c48b1a 144 debugs(42, 5, HERE << "Send ICMP packet to " << to << ".");
cc192b50 145
146 x = sendto(icmp_sock,
26ac0430
AJ
147 (const void *) pkt,
148 icmp_pktsize,
149 0,
150 S->ai_addr,
151 S->ai_addrlen);
cc192b50 152
26ac0430 153 if (x < 0) {
e0236918 154 debugs(42, DBG_IMPORTANT, HERE << "Error sending to ICMP packet to " << to << ". ERR: " << xstrerror());
cc192b50 155 }
156
157 Log(to, ' ', NULL, 0, 0);
f1402d4e 158 to.FreeAddrInfo(S);
cc192b50 159}
160
161void
b826ffb5 162Icmp4::Recv(void)
cc192b50 163{
164 int n;
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;
170 struct timeval now;
171 icmpEchoData *echo;
172 static pingerReplyData preply;
173
26ac0430 174 if (icmp_sock < 0) {
fa84c01d 175 debugs(42, DBG_CRITICAL, HERE << "No socket! Recv() should not be called.");
cc192b50 176 return;
177 }
178
179 if (pkt == NULL)
180 pkt = (char *)xmalloc(MAX_PKT4_SZ);
181
182 preply.from.InitAddrInfo(from);
183 n = recvfrom(icmp_sock,
184 (void *)pkt,
185 MAX_PKT4_SZ,
186 0,
187 from->ai_addr,
188 &from->ai_addrlen);
189
190 preply.from = *from;
191
192#if GETTIMEOFDAY_NO_TZP
193
194 gettimeofday(&now);
195
196#else
197
198 gettimeofday(&now, NULL);
199
200#endif
201
202 debugs(42, 8, HERE << n << " bytes from " << preply.from);
203
204 ip = (struct iphdr *) (void *) pkt;
205
206#if HAVE_STRUCT_IPHDR_IP_HL
207
208 iphdrlen = ip->ip_hl << 2;
209
210#else /* HAVE_STRUCT_IPHDR_IP_HL */
211#if WORDS_BIGENDIAN
212
213 iphdrlen = (ip->ip_vhl >> 4) << 2;
214
215#else
216
217 iphdrlen = (ip->ip_vhl & 0xF) << 2;
218
219#endif
220#endif /* HAVE_STRUCT_IPHDR_IP_HL */
221
222 icmp = (struct icmphdr *) (void *) (pkt + iphdrlen);
223
f1402d4e
AJ
224 if (icmp->icmp_type != ICMP_ECHOREPLY) {
225 preply.from.FreeAddrInfo(from);
cc192b50 226 return;
f1402d4e 227 }
cc192b50 228
f1402d4e
AJ
229 if (icmp->icmp_id != icmp_ident) {
230 preply.from.FreeAddrInfo(from);
cc192b50 231 return;
f1402d4e 232 }
cc192b50 233
234 echo = (icmpEchoData *) (void *) (icmp + 1);
235
236 preply.opcode = echo->opcode;
237
238 preply.hops = ipHops(ip->ip_ttl);
239
c3c6695b 240 struct timeval tv;
241 memcpy(&tv, &echo->tv, sizeof(struct timeval));
242 preply.rtt = tvSubMsec(tv, now);
cc192b50 243
244 preply.psize = n - iphdrlen - (sizeof(icmpEchoData) - MAX_PKT4_SZ);
245
246 control.SendResult(preply, (sizeof(pingerReplyData) - MAX_PKT4_SZ + preply.psize) );
247
248 Log(preply.from, icmp->icmp_type, icmpPktStr[icmp->icmp_type], preply.rtt, preply.hops);
f1402d4e 249 preply.from.FreeAddrInfo(from);
cc192b50 250}
251
252#endif /* USE_ICMP */