IcmpPinger.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2025 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 
13 #include "squid.h"
14 
15 #if USE_ICMP
16 
17 #include "compat/socket.h"
18 #include "compat/unistd.h"
19 #include "debug/Stream.h"
20 #include "Icmp4.h"
21 #include "Icmp6.h"
22 #include "IcmpPinger.h"
23 
24 #include <cerrno>
25 
27 {
28  // these start invalid. Setup properly in Open()
29  socket_from_squid = -1;
30  socket_to_squid = -1;
31 }
32 
34 {
35  Close();
36 }
37 
38 #if _SQUID_WINDOWS_
39 void
40 Win32SockCleanup(void)
41 {
42  WSACleanup();
43  return;
44 }
45 #endif
46 
47 int
49 {
50 #if _SQUID_WINDOWS_
51 
52  WSADATA wsaData;
53  WSAPROTOCOL_INFO wpi;
54  char buf[sizeof(wpi)];
55  int x;
56 
57  struct sockaddr_in PS;
58  int xerrno;
59 
60  WSAStartup(2, &wsaData);
61  atexit(Win32SockCleanup);
62 
64 
65  Debug::debugOptions = xstrdup("ALL,1");
67 
68  setmode(0, O_BINARY);
69  setmode(1, O_BINARY);
70  x = xread(0, buf, sizeof(wpi));
71 
72  if (x < (int)sizeof(wpi)) {
73  xerrno = errno;
75  debugs(42, DBG_CRITICAL, MYNAME << " read: FD 0: " << xstrerr(xerrno));
76  xwrite(1, "ERR\n", 4);
77  return -1;
78  }
79 
80  memcpy(&wpi, buf, sizeof(wpi));
81 
82  xwrite(1, "OK\n", 3);
83  x = xread(0, buf, sizeof(PS));
84 
85  if (x < (int)sizeof(PS)) {
86  xerrno = errno;
88  debugs(42, DBG_CRITICAL, MYNAME << " read: FD 0: " << xstrerr(xerrno));
89  xwrite(1, "ERR\n", 4);
90  return -1;
91  }
92 
93  memcpy(&PS, buf, sizeof(PS));
94 
95  icmp_sock = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, &wpi, 0, 0);
96 
97  if (icmp_sock == -1) {
98  xerrno = errno;
100  debugs(42, DBG_CRITICAL, MYNAME << "WSASocket: " << xstrerr(xerrno));
101  xwrite(1, "ERR\n", 4);
102  return -1;
103  }
104 
105  x = xconnect(icmp_sock, (struct sockaddr *) &PS, sizeof(PS));
106 
107  if (x != 0) {
108  xerrno = errno;
109  getCurrentTime();
110  debugs(42, DBG_CRITICAL, MYNAME << "connect: " << xstrerr(xerrno));
111  xwrite(1, "ERR\n", 4);
112  return -1;
113  }
114 
115  xwrite(1, "OK\n", 3);
116  memset(buf, 0, sizeof(buf));
117  x = xrecv(icmp_sock, buf, sizeof(buf), 0);
118 
119  if (x < 3) {
120  xerrno = errno;
121  debugs(42, DBG_CRITICAL, MYNAME << "recv: " << xstrerr(xerrno));
122  return -1;
123  }
124 
125  x = xsend(icmp_sock, buf, strlen(buf), 0);
126  xerrno = errno;
127 
128  if (x < 3 || strncmp("OK\n", buf, 3)) {
129  debugs(42, DBG_CRITICAL, MYNAME << "recv: " << xstrerr(xerrno));
130  return -1;
131  }
132 
133  getCurrentTime();
134  debugs(42, DBG_IMPORTANT, "Squid socket opened");
135 
136  /* windows uses a socket stream as a dual-direction channel */
139 
140  return icmp_sock;
141 
142 #else /* !_SQUID_WINDOWS_ */
143 
144  /* non-windows apps use stdin/out pipes as the squid channel(s) */
145  socket_from_squid = 0; // use STDIN macro ??
146  socket_to_squid = 1; // use STDOUT macro ??
147  return socket_to_squid;
148 #endif
149 }
150 
151 void
153 {
154 #if _SQUID_WINDOWS_
155 
156  shutdown(icmp_sock, SD_BOTH);
157  xclose(icmp_sock);
158  icmp_sock = -1;
159 #endif
160 
161  /* also shutdown the helper engines */
162  icmp4.Close();
163  icmp6.Close();
164 }
165 
166 void
168 {
169  static pingerEchoData pecho;
170  int n;
171  int guess_size;
172 
173  pecho = pingerEchoData();
174  n = xrecv(socket_from_squid, &pecho, sizeof(pecho), 0);
175 
176  if (n < 0) {
177  debugs(42, DBG_IMPORTANT, "Pinger exiting.");
178  Close();
179  exit(EXIT_FAILURE);
180  }
181 
182  if (0 == n) {
183  /* EOF indicator */
184  debugs(42, DBG_CRITICAL, "EOF encountered. Pinger exiting.");
185  errno = 0;
186  Close();
187  exit(EXIT_FAILURE);
188  }
189 
190  guess_size = n - (sizeof(pingerEchoData) - PINGER_PAYLOAD_SZ);
191 
192  if (guess_size != pecho.psize) {
193  debugs(42, 2, "size mismatch, guess=" << guess_size << ", psize=" << pecho.psize);
194  /* don't process this message, but keep running */
195  return;
196  }
197 
198  /* pass request for ICMPv6 handing */
199  if (pecho.to.isIPv6()) {
200  debugs(42, 2, " Pass " << pecho.to << " off to ICMPv6 module.");
201  icmp6.SendEcho(pecho.to,
202  pecho.opcode,
203  pecho.payload,
204  pecho.psize);
205  }
206 
207  /* pass the packet for ICMP handling */
208  else if (pecho.to.isIPv4()) {
209  debugs(42, 2, " Pass " << pecho.to << " off to ICMPv4 module.");
210  icmp4.SendEcho(pecho.to,
211  pecho.opcode,
212  pecho.payload,
213  pecho.psize);
214  } else {
215  debugs(42, DBG_IMPORTANT, "ERROR: IP has unknown Type. " << pecho.to );
216  }
217 }
218 
219 void
221 {
222  debugs(42, 2, "return result to squid. len=" << len);
223 
224  if (xsend(socket_to_squid, &preply, len, 0) < 0) {
225  int xerrno = errno;
226  debugs(42, DBG_CRITICAL, "FATAL: send failure: " << xstrerr(xerrno));
227  Close();
228  exit(EXIT_FAILURE);
229  }
230 }
231 
232 #endif /* USE_ICMP */
233 
static char * debugOptions
Definition: Stream.h:80
const char * xstrerr(int error)
Definition: xstrerror.cc:83
#define DBG_CRITICAL
Definition: Stream.h:37
Icmp4 icmp4
pinger helper contains one of these as a global object.
Definition: pinger.cc:93
#define PINGER_PAYLOAD_SZ
Definition: Icmp.h:16
#define xstrdup
int xwrite(int fd, const void *buf, size_t bufSize)
POSIX write(2) equivalent.
Definition: unistd.h:67
int socket_to_squid
Definition: IcmpPinger.h:47
virtual void Close()
Shutdown pinger helper and control channel.
Definition: Icmp.cc:26
bool isIPv4() const
Definition: Address.cc:178
int icmp_sock
Definition: Icmp.h:121
char payload[PINGER_PAYLOAD_SZ]
Definition: Icmp.h:31
ssize_t xsend(int socketFd, const void *buf, size_t bufLength, int flags)
POSIX send(2) equivalent.
Definition: socket.h:110
#define O_BINARY
Definition: defines.h:134
time_t getCurrentTime() STUB_RETVAL(0) int tvSubUsec(struct timeval
bool isIPv6() const
Definition: Address.cc:184
void SendEcho(Ip::Address &, int, const char *, int) override
Definition: Icmp6.cc:119
Ip::Address to
Definition: Icmp.h:28
~IcmpPinger() override
Definition: IcmpPinger.cc:33
unsigned char opcode
Definition: Icmp.h:29
int psize
Definition: Icmp.h:30
void SendResult(pingerReplyData &preply, int len)
Send ICMP results back to squid.
Definition: IcmpPinger.cc:220
int Open() override
Start and initiate control channel to squid.
Definition: IcmpPinger.cc:48
ssize_t xrecv(int socketFd, void *buf, size_t bufLength, int flags)
POSIX recv(2) equivalent.
Definition: socket.h:98
int socket_from_squid
Definition: IcmpPinger.h:46
void Close() override
Shutdown pinger helper and control channel.
Definition: IcmpPinger.cc:152
static void Win32SockCleanup(void)
int xread(int fd, void *buf, size_t bufSize)
POSIX read(2) equivalent.
Definition: unistd.h:61
#define DBG_IMPORTANT
Definition: Stream.h:38
#define MYNAME
Definition: Stream.h:219
void Recv(void) override
Handle ICMP requests from squid, passing to helpers.
Definition: IcmpPinger.cc:167
void SendEcho(Ip::Address &, int, const char *, int) override
Definition: Icmp4.cc:84
int xclose(int fd)
POSIX close(2) equivalent.
Definition: unistd.h:43
static void BanCacheLogUse()
Definition: debug.cc:1118
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:192
int xconnect(int socketFd, const struct sockaddr *sa, socklen_t saLength)
POSIX connect(2) equivalent.
Definition: socket.h:74
Icmp6 icmp6
pinger helper contains one of these as a global object.
Definition: pinger.cc:94
Definition: Icmp.h:67

 

Introduction

Documentation

Support

Miscellaneous