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