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

 

Introduction

Documentation

Support

Miscellaneous