]> git.ipfire.org Git - thirdparty/squid.git/blame - src/icmp/Icmp4.cc
Bug 3610: peername_regex ACL
[thirdparty/squid.git] / src / icmp / Icmp4.cc
CommitLineData
cc192b50 1/*
262a0e14 2 * $Id$
cc192b50 3 *
4 * DEBUG: section 42 ICMP Pinger program
5 * AUTHOR: Duane Wessels, Amos Jeffries
6 *
7 * SQUID Web Proxy Cache http://www.squid-cache.org/
8 * ----------------------------------------------------------
9 *
10 * Squid is the result of efforts by numerous individuals from
11 * the Internet community; see the CONTRIBUTORS file for full
12 * details. Many organizations have provided support for Squid's
13 * development; see the SPONSORS file for full details. Squid is
14 * Copyrighted (C) 2001 by the Regents of the University of
15 * California; see the COPYRIGHT file for full details. Squid
16 * incorporates software developed and/or copyrighted by other
17 * sources; see the CREDITS file for full details.
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
26ac0430 23 *
cc192b50 24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
26ac0430 28 *
cc192b50 29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
32 *
33 */
34//#define SQUID_HELPER 1
35
f7f3304a 36#include "squid-old.h"
cc192b50 37
38#if USE_ICMP
39
40#include "SquidTime.h"
b826ffb5
AJ
41#include "Icmp4.h"
42#include "IcmpPinger.h"
cc192b50 43#include "Debug.h"
44
26ac0430
AJ
45const char *icmpPktStr[] = {
46 "Echo Reply",
47 "ICMP 1",
48 "ICMP 2",
49 "Destination Unreachable",
50 "Source Quench",
51 "Redirect",
52 "ICMP 6",
53 "ICMP 7",
54 "Echo",
55 "ICMP 9",
56 "ICMP 10",
57 "Time Exceeded",
58 "Parameter Problem",
59 "Timestamp",
60 "Timestamp Reply",
61 "Info Request",
62 "Info Reply",
63 "Out of Range Type"
64};
cc192b50 65
b826ffb5 66Icmp4::Icmp4() : Icmp()
26ac0430
AJ
67{
68 ;
cc192b50 69}
70
b826ffb5 71Icmp4::~Icmp4()
cc192b50 72{
73 Close();
74}
75
76int
b826ffb5 77Icmp4::Open(void)
cc192b50 78{
79 icmp_sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
80
81 if (icmp_sock < 0) {
fa84c01d 82 debugs(50, DBG_CRITICAL, HERE << " icmp_sock: " << xstrerror());
cc192b50 83 return -1;
84 }
85
86 icmp_ident = getpid() & 0xffff;
e0236918 87 debugs(42, DBG_IMPORTANT, "pinger: ICMP socket opened.");
cc192b50 88
89 return icmp_sock;
90}
91
92void
b7ac5457 93Icmp4::SendEcho(Ip::Address &to, int opcode, const char *payload, int len)
cc192b50 94{
95 int x;
96 LOCAL_ARRAY(char, pkt, MAX_PKT4_SZ);
97
98 struct icmphdr *icmp = NULL;
99 icmpEchoData *echo;
100 size_t icmp_pktsize = sizeof(struct icmphdr);
101 struct addrinfo *S = NULL;
102
103 memset(pkt, '\0', MAX_PKT4_SZ);
104
105 icmp = (struct icmphdr *) (void *) pkt;
106
107 /*
108 * cevans - beware signed/unsigned issues in untrusted data from
109 * the network!!
110 */
26ac0430 111 if (len < 0) {
cc192b50 112 len = 0;
113 }
114
115 // Construct ICMP packet header
116 icmp->icmp_type = ICMP_ECHO;
117 icmp->icmp_code = 0;
118 icmp->icmp_cksum = 0;
119 icmp->icmp_id = icmp_ident;
aec55359
FC
120 icmp->icmp_seq = (unsigned short) icmp_pkts_sent;
121 ++icmp_pkts_sent;
cc192b50 122
123 // Construct ICMP packet data content
124 echo = (icmpEchoData *) (icmp + 1);
125 echo->opcode = (unsigned char) opcode;
c3c6695b 126 memcpy(&echo->tv, &current_time, sizeof(struct timeval));
cc192b50 127
128 icmp_pktsize += sizeof(struct timeval) + sizeof(char);
129
26ac0430 130 if (payload) {
cc192b50 131 if (len > MAX_PAYLOAD)
132 len = MAX_PAYLOAD;
133
41d00cd3 134 memcpy(echo->payload, payload, len);
cc192b50 135
136 icmp_pktsize += len;
137 }
138
f45dd259 139 icmp->icmp_cksum = CheckSum((unsigned short *) icmp, icmp_pktsize);
cc192b50 140
141 to.GetAddrInfo(S);
142 ((sockaddr_in*)S->ai_addr)->sin_port = 0;
143 assert(icmp_pktsize <= MAX_PKT4_SZ);
144
30c48b1a 145 debugs(42, 5, HERE << "Send ICMP packet to " << to << ".");
cc192b50 146
147 x = sendto(icmp_sock,
26ac0430
AJ
148 (const void *) pkt,
149 icmp_pktsize,
150 0,
151 S->ai_addr,
152 S->ai_addrlen);
cc192b50 153
26ac0430 154 if (x < 0) {
e0236918 155 debugs(42, DBG_IMPORTANT, HERE << "Error sending to ICMP packet to " << to << ". ERR: " << xstrerror());
cc192b50 156 }
157
158 Log(to, ' ', NULL, 0, 0);
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
224 if (icmp->icmp_type != ICMP_ECHOREPLY)
225 return;
226
227 if (icmp->icmp_id != icmp_ident)
228 return;
229
230 echo = (icmpEchoData *) (void *) (icmp + 1);
231
232 preply.opcode = echo->opcode;
233
234 preply.hops = ipHops(ip->ip_ttl);
235
c3c6695b 236 struct timeval tv;
237 memcpy(&tv, &echo->tv, sizeof(struct timeval));
238 preply.rtt = tvSubMsec(tv, now);
cc192b50 239
240 preply.psize = n - iphdrlen - (sizeof(icmpEchoData) - MAX_PKT4_SZ);
241
242 control.SendResult(preply, (sizeof(pingerReplyData) - MAX_PKT4_SZ + preply.psize) );
243
244 Log(preply.from, icmp->icmp_type, icmpPktStr[icmp->icmp_type], preply.rtt, preply.hops);
245}
246
247#endif /* USE_ICMP */