]> git.ipfire.org Git - thirdparty/squid.git/blob - src/icmp/Icmp4.cc
Merged Postfix-Prefix branch: refactor inc/decrement operators from postfix to prefix...
[thirdparty/squid.git] / src / icmp / Icmp4.cc
1 /*
2 * $Id$
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.
23 *
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.
28 *
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
36 #include "squid-old.h"
37
38 #if USE_ICMP
39
40 #include "SquidTime.h"
41 #include "Icmp4.h"
42 #include "IcmpPinger.h"
43 #include "Debug.h"
44
45 const 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 };
65
66 Icmp4::Icmp4() : Icmp()
67 {
68 ;
69 }
70
71 Icmp4::~Icmp4()
72 {
73 Close();
74 }
75
76 int
77 Icmp4::Open(void)
78 {
79 icmp_sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
80
81 if (icmp_sock < 0) {
82 debugs(50, 0, HERE << " icmp_sock: " << xstrerror());
83 return -1;
84 }
85
86 icmp_ident = getpid() & 0xffff;
87 debugs(42, 1, "pinger: ICMP socket opened.");
88
89 return icmp_sock;
90 }
91
92 void
93 Icmp4::SendEcho(Ip::Address &to, int opcode, const char *payload, int len)
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 */
111 if (len < 0) {
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;
120 icmp->icmp_seq = (unsigned short) icmp_pkts_sent;
121 ++icmp_pkts_sent;
122
123 // Construct ICMP packet data content
124 echo = (icmpEchoData *) (icmp + 1);
125 echo->opcode = (unsigned char) opcode;
126 memcpy(&echo->tv, &current_time, sizeof(struct timeval));
127
128 icmp_pktsize += sizeof(struct timeval) + sizeof(char);
129
130 if (payload) {
131 if (len > MAX_PAYLOAD)
132 len = MAX_PAYLOAD;
133
134 memcpy(echo->payload, payload, len);
135
136 icmp_pktsize += len;
137 }
138
139 icmp->icmp_cksum = CheckSum((unsigned short *) icmp, icmp_pktsize);
140
141 to.GetAddrInfo(S);
142 ((sockaddr_in*)S->ai_addr)->sin_port = 0;
143 assert(icmp_pktsize <= MAX_PKT4_SZ);
144
145 debugs(42, 5, HERE << "Send ICMP packet to " << to << ".");
146
147 x = sendto(icmp_sock,
148 (const void *) pkt,
149 icmp_pktsize,
150 0,
151 S->ai_addr,
152 S->ai_addrlen);
153
154 if (x < 0) {
155 debugs(42, 1, HERE << "Error sending to ICMP packet to " << to << ". ERR: " << xstrerror());
156 }
157
158 Log(to, ' ', NULL, 0, 0);
159 }
160
161 void
162 Icmp4::Recv(void)
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
174 if (icmp_sock < 0) {
175 debugs(42, 0, HERE << "No socket! Recv() should not be called.");
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
236 struct timeval tv;
237 memcpy(&tv, &echo->tv, sizeof(struct timeval));
238 preply.rtt = tvSubMsec(tv, now);
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 */