]>
Commit | Line | Data |
---|---|---|
cc192b50 | 1 | /* |
bbc27441 | 2 | * Copyright (C) 1996-2014 The Squid Software Foundation and contributors |
cc192b50 | 3 | * |
bbc27441 AJ |
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. | |
cc192b50 | 7 | */ |
8 | ||
bbc27441 AJ |
9 | /* DEBUG: section 42 ICMP Pinger program */ |
10 | ||
cc192b50 | 11 | #define SQUID_HELPER 1 |
12 | ||
582c2af2 | 13 | #include "squid.h" |
cc192b50 | 14 | |
15 | #if USE_ICMP | |
16 | ||
602d9612 | 17 | #include "Debug.h" |
b826ffb5 AJ |
18 | #include "Icmp4.h" |
19 | #include "Icmp6.h" | |
602d9612 A |
20 | #include "IcmpPinger.h" |
21 | #include "SquidTime.h" | |
cc192b50 | 22 | |
1a30fdf5 | 23 | #include <cerrno> |
21d845b1 | 24 | |
b826ffb5 | 25 | IcmpPinger::IcmpPinger() : Icmp() |
cc192b50 | 26 | { |
27 | // these start invalid. Setup properly in Open() | |
28 | socket_from_squid = -1; | |
29 | socket_to_squid = -1; | |
30 | } | |
31 | ||
b826ffb5 | 32 | IcmpPinger::~IcmpPinger() |
cc192b50 | 33 | { |
34 | Close(); | |
35 | } | |
36 | ||
7aa9bb3e | 37 | #if _SQUID_WINDOWS_ |
ec556193 GS |
38 | void |
39 | Win32SockCleanup(void) | |
40 | { | |
41 | WSACleanup(); | |
42 | return; | |
43 | } | |
44 | #endif | |
45 | ||
cc192b50 | 46 | int |
b826ffb5 | 47 | IcmpPinger::Open(void) |
cc192b50 | 48 | { |
7aa9bb3e | 49 | #if _SQUID_WINDOWS_ |
cc192b50 | 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); | |
ec556193 | 59 | atexit(Win32SockCleanup); |
cc192b50 | 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(); | |
fa84c01d | 69 | debugs(42, DBG_CRITICAL, HERE << "read: FD 0: " << xstrerror()); |
cc192b50 | 70 | write(1, "ERR\n", 4); |
71 | return -1; | |
72 | } | |
73 | ||
41d00cd3 | 74 | memcpy(&wpi, buf, sizeof(wpi)); |
cc192b50 | 75 | |
76 | write(1, "OK\n", 3); | |
77 | x = read(0, buf, sizeof(PS)); | |
78 | ||
79 | if (x < (int)sizeof(PS)) { | |
80 | getCurrentTime(); | |
fa84c01d | 81 | debugs(42, DBG_CRITICAL, HERE << "read: FD 0: " << xstrerror()); |
cc192b50 | 82 | write(1, "ERR\n", 4); |
83 | return -1; | |
84 | } | |
85 | ||
41d00cd3 | 86 | memcpy(&PS, buf, sizeof(PS)); |
cc192b50 | 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(); | |
fa84c01d | 92 | debugs(42, DBG_CRITICAL, HERE << "WSASocket: " << xstrerror()); |
cc192b50 | 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(); | |
fa84c01d | 101 | debugs(42, DBG_CRITICAL, HERE << "connect: " << xstrerror()); |
cc192b50 | 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) { | |
fa84c01d | 111 | debugs(42, DBG_CRITICAL, HERE << "recv: " << xstrerror()); |
cc192b50 | 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)) { | |
fa84c01d | 118 | debugs(42, DBG_CRITICAL, HERE << "recv: " << xstrerror()); |
cc192b50 | 119 | return -1; |
120 | } | |
121 | ||
122 | getCurrentTime(); | |
e0236918 | 123 | debugs(42, DBG_IMPORTANT, "pinger: Squid socket opened"); |
cc192b50 | 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 | ||
7aa9bb3e | 131 | #else /* !_SQUID_WINDOWS_ */ |
cc192b50 | 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 | |
b826ffb5 | 141 | IcmpPinger::Close(void) |
cc192b50 | 142 | { |
7aa9bb3e | 143 | #if _SQUID_WINDOWS_ |
cc192b50 | 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(); | |
cc192b50 | 152 | icmp6.Close(); |
cc192b50 | 153 | } |
154 | ||
155 | void | |
b826ffb5 | 156 | IcmpPinger::Recv(void) |
cc192b50 | 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) { | |
e0236918 | 166 | debugs(42, DBG_IMPORTANT, "Pinger exiting."); |
cc192b50 | 167 | Close(); |
168 | exit(1); | |
169 | } | |
170 | ||
171 | if (0 == n) { | |
172 | /* EOF indicator */ | |
fa84c01d | 173 | debugs(42, DBG_CRITICAL, HERE << "EOF encountered. Pinger exiting.\n"); |
cc192b50 | 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 | ||
cc192b50 | 187 | /* pass request for ICMPv6 handing */ |
4dd643d5 | 188 | if (pecho.to.isIPv6()) { |
cc192b50 | 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 | } | |
cc192b50 | 195 | |
196 | /* pass the packet for ICMP handling */ | |
4dd643d5 | 197 | else if (pecho.to.isIPv4()) { |
cc192b50 | 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); | |
26ac0430 | 203 | } else { |
e0236918 | 204 | debugs(42, DBG_IMPORTANT, HERE << " IP has unknown Type. " << pecho.to ); |
cc192b50 | 205 | } |
206 | } | |
207 | ||
208 | void | |
b826ffb5 | 209 | IcmpPinger::SendResult(pingerReplyData &preply, int len) |
cc192b50 | 210 | { |
211 | debugs(42, 2, HERE << "return result to squid. len=" << len); | |
212 | ||
213 | if (send(socket_to_squid, &preply, len, 0) < 0) { | |
fa84c01d | 214 | debugs(42, DBG_CRITICAL, "pinger: FATAL error on send: " << xstrerror()); |
cc192b50 | 215 | Close(); |
216 | exit(1); | |
217 | } | |
218 | } | |
219 | ||
220 | #endif /* USE_ICMP */ | |
f53969cc | 221 |