]> git.ipfire.org Git - thirdparty/squid.git/blob - src/icmp/IcmpPinger.cc
Merged from trunk r12948.
[thirdparty/squid.git] / src / icmp / IcmpPinger.cc
1 /*
2 * DEBUG: section 42 ICMP Pinger program
3 * AUTHOR: Duane Wessels
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.
21 *
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.
26 *
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
33 #define SQUID_HELPER 1
34
35 #include "squid.h"
36
37 #if USE_ICMP
38
39 #include "SquidTime.h"
40 #include "IcmpPinger.h"
41 #include "Icmp4.h"
42 #include "Icmp6.h"
43 #include "Debug.h"
44
45 #if HAVE_ERRNO_H
46 #include <errno.h>
47 #endif
48
49 IcmpPinger::IcmpPinger() : Icmp()
50 {
51 // these start invalid. Setup properly in Open()
52 socket_from_squid = -1;
53 socket_to_squid = -1;
54 }
55
56 IcmpPinger::~IcmpPinger()
57 {
58 Close();
59 }
60
61 #if _SQUID_WINDOWS_
62 void
63 Win32SockCleanup(void)
64 {
65 WSACleanup();
66 return;
67 }
68 #endif
69
70 int
71 IcmpPinger::Open(void)
72 {
73 #if _SQUID_WINDOWS_
74
75 WSADATA wsaData;
76 WSAPROTOCOL_INFO wpi;
77 char buf[sizeof(wpi)];
78 int x;
79
80 struct sockaddr_in PS;
81
82 WSAStartup(2, &wsaData);
83 atexit(Win32SockCleanup);
84
85 getCurrentTime();
86 _db_init(NULL, "ALL,1");
87 setmode(0, O_BINARY);
88 setmode(1, O_BINARY);
89 x = read(0, buf, sizeof(wpi));
90
91 if (x < (int)sizeof(wpi)) {
92 getCurrentTime();
93 debugs(42, DBG_CRITICAL, HERE << "read: FD 0: " << xstrerror());
94 write(1, "ERR\n", 4);
95 return -1;
96 }
97
98 memcpy(&wpi, buf, sizeof(wpi));
99
100 write(1, "OK\n", 3);
101 x = read(0, buf, sizeof(PS));
102
103 if (x < (int)sizeof(PS)) {
104 getCurrentTime();
105 debugs(42, DBG_CRITICAL, HERE << "read: FD 0: " << xstrerror());
106 write(1, "ERR\n", 4);
107 return -1;
108 }
109
110 memcpy(&PS, buf, sizeof(PS));
111
112 icmp_sock = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, &wpi, 0, 0);
113
114 if (icmp_sock == -1) {
115 getCurrentTime();
116 debugs(42, DBG_CRITICAL, HERE << "WSASocket: " << xstrerror());
117 write(1, "ERR\n", 4);
118 return -1;
119 }
120
121 x = connect(icmp_sock, (struct sockaddr *) &PS, sizeof(PS));
122
123 if (SOCKET_ERROR == x) {
124 getCurrentTime();
125 debugs(42, DBG_CRITICAL, HERE << "connect: " << xstrerror());
126 write(1, "ERR\n", 4);
127 return -1;
128 }
129
130 write(1, "OK\n", 3);
131 memset(buf, 0, sizeof(buf));
132 x = recv(icmp_sock, (void *) buf, sizeof(buf), 0);
133
134 if (x < 3) {
135 debugs(42, DBG_CRITICAL, HERE << "recv: " << xstrerror());
136 return -1;
137 }
138
139 x = send(icmp_sock, (const void *) buf, strlen(buf), 0);
140
141 if (x < 3 || strncmp("OK\n", buf, 3)) {
142 debugs(42, DBG_CRITICAL, HERE << "recv: " << xstrerror());
143 return -1;
144 }
145
146 getCurrentTime();
147 debugs(42, DBG_IMPORTANT, "pinger: Squid socket opened");
148
149 /* windows uses a socket stream as a dual-direction channel */
150 socket_to_squid = icmp_sock;
151 socket_from_squid = icmp_sock;
152
153 return icmp_sock;
154
155 #else /* !_SQUID_WINDOWS_ */
156
157 /* non-windows apps use stdin/out pipes as the squid channel(s) */
158 socket_from_squid = 0; // use STDIN macro ??
159 socket_to_squid = 1; // use STDOUT macro ??
160 return socket_to_squid;
161 #endif
162 }
163
164 void
165 IcmpPinger::Close(void)
166 {
167 #if _SQUID_WINDOWS_
168
169 shutdown(icmp_sock, SD_BOTH);
170 close(icmp_sock);
171 icmp_sock = -1;
172 #endif
173
174 /* also shutdown the helper engines */
175 icmp4.Close();
176 icmp6.Close();
177 }
178
179 void
180 IcmpPinger::Recv(void)
181 {
182 static pingerEchoData pecho;
183 int n;
184 int guess_size;
185
186 memset(&pecho, '\0', sizeof(pecho));
187 n = recv(socket_from_squid, &pecho, sizeof(pecho), 0);
188
189 if (n < 0) {
190 debugs(42, DBG_IMPORTANT, "Pinger exiting.");
191 Close();
192 exit(1);
193 }
194
195 if (0 == n) {
196 /* EOF indicator */
197 debugs(42, DBG_CRITICAL, HERE << "EOF encountered. Pinger exiting.\n");
198 errno = 0;
199 Close();
200 exit(1);
201 }
202
203 guess_size = n - (sizeof(pingerEchoData) - PINGER_PAYLOAD_SZ);
204
205 if (guess_size != pecho.psize) {
206 debugs(42, 2, HERE << "size mismatch, guess=" << guess_size << ", psize=" << pecho.psize);
207 /* don't process this message, but keep running */
208 return;
209 }
210
211 /* pass request for ICMPv6 handing */
212 if (pecho.to.isIPv6()) {
213 debugs(42, 2, HERE << " Pass " << pecho.to << " off to ICMPv6 module.");
214 icmp6.SendEcho(pecho.to,
215 pecho.opcode,
216 pecho.payload,
217 pecho.psize);
218 }
219
220 /* pass the packet for ICMP handling */
221 else if (pecho.to.isIPv4()) {
222 debugs(42, 2, HERE << " Pass " << pecho.to << " off to ICMPv4 module.");
223 icmp4.SendEcho(pecho.to,
224 pecho.opcode,
225 pecho.payload,
226 pecho.psize);
227 } else {
228 debugs(42, DBG_IMPORTANT, HERE << " IP has unknown Type. " << pecho.to );
229 }
230 }
231
232 void
233 IcmpPinger::SendResult(pingerReplyData &preply, int len)
234 {
235 debugs(42, 2, HERE << "return result to squid. len=" << len);
236
237 if (send(socket_to_squid, &preply, len, 0) < 0) {
238 debugs(42, DBG_CRITICAL, "pinger: FATAL error on send: " << xstrerror());
239 Close();
240 exit(1);
241 }
242 }
243
244 #endif /* USE_ICMP */