pinger.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* DEBUG: section 42 ICMP Pinger program */
10 
11 #define SQUID_HELPER 1
12 
42 #include "squid.h"
43 #include "Debug.h"
44 #include "SquidTime.h"
45 
46 #if USE_ICMP
47 
48 #include "Icmp4.h"
49 #include "Icmp6.h"
50 #include "IcmpPinger.h"
51 #include "ip/tools.h"
52 
53 #if _SQUID_WINDOWS_
54 
55 #if HAVE_WINSOCK2_H
56 #include <winsock2.h>
57 #elif HAVE_WINSOCK_H
58 #include <winsock.h>
59 #endif
60 #include <process.h>
61 #include "fde.h"
62 
63 #define PINGER_TIMEOUT 5
64 
65 /* windows uses the control socket for feedback to squid */
66 #define LINK_TO_SQUID squid_link
67 
68 // windows still requires WSAFD but there are too many dependancy problems
69 // to just link to win32.cc where it is normally defined.
70 
71 int
72 Win32__WSAFDIsSet(int fd, fd_set FAR * set)
73 {
74  fde *F = &fd_table[fd];
75  SOCKET s = F->win32.handle;
76 
77  return __WSAFDIsSet(s, set);
78 }
79 
80 #else
81 
82 #define PINGER_TIMEOUT 10
83 
84 /* non-windows use STDOUT for feedback to squid */
85 #define LINK_TO_SQUID 1
86 
87 #endif /* _SQUID_WINDOWS_ */
88 
89 // ICMP Engines are declared global here so they can call each other easily.
93 
95 
103 int
104 main(int argc, char *argv[])
105 {
106  fd_set R;
107  int x;
108  int max_fd = 0;
109 
110  struct timeval tv;
111  const char *debug_args = "ALL,10";
112  char *t;
113  time_t last_check_time = 0;
114 
115  /*
116  * cevans - do this first. It grabs a raw socket. After this we can
117  * drop privs
118  */
119  int icmp4_worker = -1;
120  int icmp6_worker = -1;
121  int squid_link = -1;
122 
124  if ((t = getenv("SQUID_DEBUG")))
125  debug_args = xstrdup(t);
126 
127  getCurrentTime();
128 
129  // determine IPv4 or IPv6 capabilities before using sockets.
131 
132  _db_init(NULL, debug_args);
133 
134  debugs(42, DBG_CRITICAL, "pinger: Initialising ICMP pinger ...");
135 
136  icmp4_worker = icmp4.Open();
137  if (icmp4_worker < 0) {
138  debugs(42, DBG_CRITICAL, "pinger: Unable to start ICMP pinger.");
139  }
140  max_fd = max(max_fd, icmp4_worker);
141 
142 #if USE_IPV6
143  icmp6_worker = icmp6.Open();
144  if (icmp6_worker <0 ) {
145  debugs(42, DBG_CRITICAL, "pinger: Unable to start ICMPv6 pinger.");
146  }
147  max_fd = max(max_fd, icmp6_worker);
148 #endif
149 
151  if (icmp4_worker < 0 && icmp6_worker < 0) {
152  debugs(42, DBG_CRITICAL, "FATAL: pinger: Unable to open any ICMP sockets.");
153  exit(EXIT_FAILURE);
154  }
155 
156  if ( (squid_link = control.Open()) < 0) {
157  debugs(42, DBG_CRITICAL, "FATAL: pinger: Unable to setup Pinger control sockets.");
158  icmp4.Close();
159  icmp6.Close();
160  exit(EXIT_FAILURE); // fatal error if the control channel fails.
161  }
162  max_fd = max(max_fd, squid_link);
163 
164  if (setgid(getgid()) < 0) {
165  int xerrno = errno;
166  debugs(42, DBG_CRITICAL, "FATAL: pinger: setgid(" << getgid() << ") failed: " << xstrerr(xerrno));
167  icmp4.Close();
168  icmp6.Close();
169  exit(EXIT_FAILURE);
170  }
171  if (setuid(getuid()) < 0) {
172  int xerrno = errno;
173  debugs(42, DBG_CRITICAL, "FATAL: pinger: setuid(" << getuid() << ") failed: " << xstrerr(xerrno));
174  icmp4.Close();
175  icmp6.Close();
176  exit(EXIT_FAILURE);
177  }
178 
179 #if USE_LIBCAP
180  // Drop remaining capabilities (if installed as non-setuid setcap cap_net_raw=ep).
181  // If pinger binary was installed setuid root, setuid() above already dropped all
182  // capabilities, and this is no-op.
183  cap_t caps;
184  caps = cap_init();
185  if (!caps) {
186  int xerrno = errno;
187  debugs(42, DBG_CRITICAL, "FATAL: pinger: cap_init() failed: " << xstrerr(xerrno));
188  icmp4.Close();
189  icmp6.Close();
190  exit(EXIT_FAILURE);
191  } else {
192  if (cap_set_proc(caps) != 0) {
193  int xerrno = errno;
194  // cap_set_proc(cap_init()) is expected to never fail
195  debugs(42, DBG_CRITICAL, "FATAL: pinger: cap_set_proc(none) failed: " << xstrerr(xerrno));
196  cap_free(caps);
197  icmp4.Close();
198  icmp6.Close();
199  exit(EXIT_FAILURE);
200  }
201  cap_free(caps);
202  }
203 #endif
204 
205  last_check_time = squid_curtime;
206 
207  for (;;) {
208  tv.tv_sec = PINGER_TIMEOUT;
209  tv.tv_usec = 0;
210  FD_ZERO(&R);
211  if (icmp4_worker >= 0) {
212  FD_SET(icmp4_worker, &R);
213  }
214  if (icmp6_worker >= 0) {
215  FD_SET(icmp6_worker, &R);
216  }
217 
218  FD_SET(squid_link, &R);
219  x = select(max_fd+1, &R, NULL, NULL, &tv);
220  getCurrentTime();
221 
222  if (x < 0) {
223  int xerrno = errno;
224  debugs(42, DBG_CRITICAL, HERE << " FATAL Shutdown. select()==" << x << ", ERR: " << xstrerr(xerrno));
225  control.Close();
226  exit(EXIT_FAILURE);
227  }
228 
229  if (FD_ISSET(squid_link, &R)) {
230  control.Recv();
231  }
232 
233  if (icmp6_worker >= 0 && FD_ISSET(icmp6_worker, &R)) {
234  icmp6.Recv();
235  }
236  if (icmp4_worker >= 0 && FD_ISSET(icmp4_worker, &R)) {
237  icmp4.Recv();
238  }
239 
240  if (PINGER_TIMEOUT + last_check_time < squid_curtime) {
241  if (send(LINK_TO_SQUID, &tv, 0, 0) < 0) {
242  debugs(42, DBG_CRITICAL, "pinger: Closing. No requests in last " << PINGER_TIMEOUT << " seconds.");
243  control.Close();
244  exit(EXIT_FAILURE);
245  }
246 
247  last_check_time = squid_curtime;
248  }
249  }
250 
251  /* NOTREACHED */
252  return EXIT_SUCCESS;
253 }
254 
255 #else /* !USE_ICMP */
256 
257 #include <ostream>
258 int
259 main(int argc, char *argv[])
260 {
261  std::cerr << argv[0] << ": ICMP support not compiled in." << std::endl;
262  return EXIT_FAILURE;
263 }
264 
265 #endif /* USE_ICMP */
266 
#define fd_table
Definition: fde.h:157
Icmp6 icmp6
pinger helper contains one of these as a global object.
Definition: pinger.cc:92
IcmpPinger control
pinger helper contains one of these as a global object.
Definition: pinger.cc:90
#define xstrdup
#define LINK_TO_SQUID
Definition: pinger.cc:85
virtual void Recv(void)
Definition: Icmp6.cc:195
virtual int Open()
Start pinger helper and initiate control channel.
Definition: Icmp6.cc:99
#define DBG_CRITICAL
Definition: Debug.h:44
Icmp4 icmp4
pinger helper contains one of these as a global object.
Definition: pinger.cc:91
A const & max(A const &lhs, A const &rhs)
time_t squid_curtime
Definition: stub_time.cc:17
const char * xstrerr(int error)
Definition: xstrerror.cc:83
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
#define PINGER_TIMEOUT
Definition: pinger.cc:82
void _db_init(const char *logfile, const char *options)
Definition: debug.cc:481
virtual int Open()
Start pinger helper and initiate control channel.
Definition: Icmp4.cc:67
virtual int Open()
Start and initiate control channel to squid.
Definition: IcmpPinger.cc:47
void ProbeTransport(void)
Probe to discover IPv6 capabilities.
int icmp_pkts_sent
Definition: pinger.cc:94
std::ostream & HERE(std::ostream &s)
Definition: Debug.h:147
time_t getCurrentTime(void)
Get current time.
Definition: fde.h:49
virtual void Recv(void)
Handle ICMP requests from squid, passing to helpers.
Definition: IcmpPinger.cc:163
static uint32 F(uint32 X, uint32 Y, uint32 Z)
Definition: md4.c:46
virtual void Recv(void)
Handle ICMP responses.
Definition: Icmp4.cc:155
int main(int argc, char *argv[])
Definition: pinger.cc:104
Definition: Icmp6.h:45
virtual void Close()
Shutdown pinger helper and control channel.
Definition: IcmpPinger.cc:148
#define NULL
Definition: types.h:166
virtual void Close()
Shutdown pinger helper and control channel.
Definition: Icmp.cc:25
Definition: Icmp4.h:133

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors