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