]>
Commit | Line | Data |
---|---|---|
9d90e665 | 1 | /* |
63be0a78 | 2 | * $Id: pinger.cc,v 1.62 2008/02/26 21:49:35 amosjeffries Exp $ |
9d90e665 | 3 | * |
f43e2ec2 | 4 | * DEBUG: section 42 ICMP Pinger program |
9d90e665 | 5 | * AUTHOR: Duane Wessels |
6 | * | |
2b6662ba | 7 | * SQUID Web Proxy Cache http://www.squid-cache.org/ |
e25c139f | 8 | * ---------------------------------------------------------- |
9d90e665 | 9 | * |
2b6662ba | 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. | |
9d90e665 | 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 | |
cbdec147 | 31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
e25c139f | 32 | * |
9d90e665 | 33 | */ |
34 | ||
128fe1c6 | 35 | #define SQUID_HELPER 1 |
36 | ||
63be0a78 | 37 | /** |
38 | \defgroup pinger pinger | |
39 | \ingroup ExternalPrograms | |
40 | \par | |
41 | * Although it would be possible for Squid to send and receive | |
42 | * ICMP messages directly, we use an external process for | |
43 | * two important reasons: | |
44 | * | |
45 | \li Because squid handles many filedescriptors simultaneously, | |
46 | * we get much more accurate RTT measurements when ICMP is | |
47 | * handled by a separate process. | |
48 | * | |
49 | \li Superuser privileges are required to send and receive ICMP. | |
50 | * Rather than require Squid to be started as root, we prefer | |
51 | * to have the smaller and simpler pinger program installed | |
52 | * with setuid permissions. | |
53 | * | |
54 | \par | |
55 | * If you want to use Squid's ICMP features (highly recommended!) | |
56 | * When USE_ICMP is defined, Squid will send ICMP pings | |
57 | * to origin server sites. | |
58 | * This information is used in numerous ways: | |
59 | \li - Sent in ICP replies so neighbor caches know how close | |
60 | * you are to the source. | |
61 | \li - For finding the closest instance of a URN. | |
62 | \li - With the 'test_reachability' option. Squid will return | |
63 | * ICP_OP_MISS_NOFETCH for sites which it cannot ping. | |
64 | */ | |
65 | ||
9d90e665 | 66 | #include "squid.h" |
985c86bc | 67 | #include "SquidTime.h" |
9d90e665 | 68 | |
43426991 | 69 | #if USE_ICMP |
70 | ||
cc192b50 | 71 | #include "ICMPv4.h" |
72 | #include "ICMPv6.h" | |
73 | #include "ICMPPinger.h" | |
0ab98d6b | 74 | |
bdb741f4 | 75 | #ifdef _SQUID_MSWIN_ |
76 | ||
bfe8dedf | 77 | #if HAVE_WINSOCK2_H |
bdb741f4 | 78 | #include <winsock2.h> |
bfe8dedf | 79 | #endif |
bdb741f4 | 80 | #include <process.h> |
cc192b50 | 81 | #include "fde.h" |
bdb741f4 | 82 | |
83 | #define PINGER_TIMEOUT 5 | |
84 | ||
cc192b50 | 85 | /* windows uses the control socket for feedback to squid */ |
86 | #define LINK_TO_SQUID squid_link | |
bdb741f4 | 87 | |
cc192b50 | 88 | // windows still requires WSAFD but there are too many dependancy problems |
89 | // to just link to win32.cc where it is normally defined. | |
bdb741f4 | 90 | |
cc192b50 | 91 | int |
92 | Win32__WSAFDIsSet(int fd, fd_set FAR * set) | |
bdb741f4 | 93 | { |
cc192b50 | 94 | fde *F = &fd_table[fd]; |
95 | SOCKET s = F->win32.handle; | |
bdb741f4 | 96 | |
cc192b50 | 97 | return __WSAFDIsSet(s, set); |
bdb741f4 | 98 | } |
99 | ||
cc192b50 | 100 | #else |
bdb741f4 | 101 | |
cc192b50 | 102 | #define PINGER_TIMEOUT 10 |
bdb741f4 | 103 | |
cc192b50 | 104 | /* non-windows use STDOUT for feedback to squid */ |
105 | #define LINK_TO_SQUID 1 | |
bdb741f4 | 106 | |
107 | #endif /* _SQUID_MSWIN_ */ | |
108 | ||
cc192b50 | 109 | // ICMP Engines are declared global here so they can call each other easily. |
110 | ICMPPinger control; | |
111 | ICMPv4 icmp4; | |
112 | #if USE_IPV6 | |
113 | ICMPv6 icmp6; | |
6637e3a5 | 114 | #endif |
62e76326 | 115 | |
5be53f2d | 116 | int icmp_pkts_sent = 0; |
9d90e665 | 117 | |
63be0a78 | 118 | /** |
119 | \ingroup pinger | |
120 | \par This is the pinger external process. | |
121 | * | |
122 | \param argc Ignored. | |
123 | \param argv Ignored. | |
124 | */ | |
cc192b50 | 125 | int |
126 | main(int argc, char *argv[]) | |
9d90e665 | 127 | { |
cc192b50 | 128 | fd_set R; |
bdb741f4 | 129 | int x; |
cc192b50 | 130 | int max_fd = 0; |
bdb741f4 | 131 | |
cc192b50 | 132 | struct timeval tv; |
133 | const char *debug_args = "ALL,10"; | |
134 | char *t; | |
135 | time_t last_check_time = 0; | |
bdb741f4 | 136 | |
cc192b50 | 137 | /* |
138 | * cevans - do this first. It grabs a raw socket. After this we can | |
139 | * drop privs | |
140 | */ | |
141 | int icmp4_worker = -1; | |
142 | #if USE_IPV6 | |
143 | int icmp6_worker = -1; | |
bdb741f4 | 144 | #endif |
cc192b50 | 145 | int squid_link = -1; |
62e76326 | 146 | |
63be0a78 | 147 | /** start by initializing the pinger debug cache.log-pinger. */ |
cc192b50 | 148 | if ((t = getenv("SQUID_DEBUG"))) |
149 | debug_args = xstrdup(t); | |
bdb741f4 | 150 | |
151 | getCurrentTime(); | |
62e76326 | 152 | |
cc192b50 | 153 | _db_init(NULL, debug_args); |
b6a2f15e | 154 | |
cc192b50 | 155 | debugs(42, 0, "pinger: Initialising ICMP pinger ..."); |
62e76326 | 156 | |
cc192b50 | 157 | icmp4_worker = icmp4.Open(); |
158 | if(icmp4_worker < 0) { | |
159 | debugs(42, 0, "pinger: Unable to start ICMP pinger."); | |
b6a2f15e | 160 | } |
cc192b50 | 161 | max_fd = max(max_fd, icmp4_worker); |
62e76326 | 162 | |
cc192b50 | 163 | #if USE_IPV6 |
164 | icmp6_worker = icmp6.Open(); | |
165 | if(icmp6_worker <0 ) { | |
166 | debugs(42, 0, "pinger: Unable to start ICMPv6 pinger."); | |
9d90e665 | 167 | } |
cc192b50 | 168 | max_fd = max(max_fd, icmp6_worker); |
d20b1cd0 | 169 | #endif |
62e76326 | 170 | |
63be0a78 | 171 | /** abort if neither worker could open a socket. */ |
cc192b50 | 172 | if(icmp4_worker == -1) { |
173 | #if USE_IPV6 | |
174 | if(icmp6_worker == -1) | |
9d90e665 | 175 | #endif |
f5b2e1ba | 176 | { |
cc192b50 | 177 | debugs(42, 0, "FATAL: pinger: Unable to open any ICMP sockets."); |
178 | exit(1); | |
f5b2e1ba | 179 | } |
b6a2f15e | 180 | } |
62e76326 | 181 | |
cc192b50 | 182 | if( (squid_link = control.Open()) < 0) { |
183 | debugs(42, 0, "FATAL: pinger: Unable to setup Pinger control sockets."); | |
184 | icmp4.Close(); | |
185 | #if USE_IPV6 | |
186 | icmp6.Close(); | |
187 | #endif | |
188 | exit(1); // fatal error if the control channel fails. | |
365a4bce | 189 | } |
cc192b50 | 190 | max_fd = max(max_fd, squid_link); |
62e76326 | 191 | |
b6a2f15e | 192 | setgid(getgid()); |
193 | setuid(getuid()); | |
194 | ||
9d90e665 | 195 | for (;;) { |
bdb741f4 | 196 | tv.tv_sec = PINGER_TIMEOUT; |
62e76326 | 197 | tv.tv_usec = 0; |
198 | FD_ZERO(&R); | |
cc192b50 | 199 | if(icmp4_worker >= 0) { |
200 | FD_SET(icmp4_worker, &R); | |
201 | } | |
202 | #if USE_IPV6 | |
203 | ||
204 | if(icmp6_worker >= 0) { | |
205 | FD_SET(icmp6_worker, &R); | |
206 | } | |
207 | #endif | |
208 | FD_SET(squid_link, &R); | |
209 | x = select(10, &R, NULL, NULL, &tv); | |
62e76326 | 210 | getCurrentTime(); |
211 | ||
bdb741f4 | 212 | if (x < 0) { |
cc192b50 | 213 | debugs(42, 0, HERE << " FATAL Shutdown. select()==" << x << ", ERR: " << xstrerror()); |
214 | control.Close(); | |
62e76326 | 215 | exit(1); |
bdb741f4 | 216 | } |
62e76326 | 217 | |
cc192b50 | 218 | if (FD_ISSET(squid_link, &R)) { |
219 | control.Recv(); | |
220 | } | |
62e76326 | 221 | |
cc192b50 | 222 | #if USE_IPV6 |
223 | if (icmp6_worker >= 0 && FD_ISSET(icmp6_worker, &R)) { | |
224 | icmp6.Recv(); | |
225 | } | |
226 | #endif | |
227 | ||
228 | if (icmp4_worker >= 0 && FD_ISSET(icmp4_worker, &R)) { | |
229 | icmp4.Recv(); | |
230 | } | |
62e76326 | 231 | |
bdb741f4 | 232 | if (PINGER_TIMEOUT + last_check_time < squid_curtime) { |
cc192b50 | 233 | if (send(LINK_TO_SQUID, &tv, 0, 0) < 0) { |
234 | debugs(42, 0, "pinger: Closing. No requests in last " << PINGER_TIMEOUT << " seconds."); | |
235 | control.Close(); | |
62e76326 | 236 | exit(1); |
bdb741f4 | 237 | } |
62e76326 | 238 | |
239 | last_check_time = squid_curtime; | |
240 | } | |
9d90e665 | 241 | } |
62e76326 | 242 | |
145766ef | 243 | /* NOTREACHED */ |
bdb741f4 | 244 | return 0; |
9d90e665 | 245 | } |
365a4bce | 246 | |
9d90e665 | 247 | #else |
248 | #include <stdio.h> | |
249 | int | |
250 | main(int argc, char *argv[]) | |
251 | { | |
252 | fprintf(stderr, "%s: ICMP support not compiled in.\n", argv[0]); | |
253 | return 1; | |
254 | } | |
62e76326 | 255 | |
9d90e665 | 256 | #endif /* USE_ICMP */ |