]>
Commit | Line | Data |
---|---|---|
6ffa5ad9 | 1 | |
fab463b4 | 2 | /* |
674ac814 | 3 | * $Id: icmp.cc,v 1.67 1998/11/13 20:50:51 wessels Exp $ |
fab463b4 | 4 | * |
5 | * DEBUG: section 37 ICMP Routines | |
6 | * AUTHOR: Duane Wessels | |
7 | * | |
42c04c16 | 8 | * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ |
e25c139f | 9 | * ---------------------------------------------------------- |
fab463b4 | 10 | * |
11 | * Squid is the result of efforts by numerous individuals from the | |
12 | * Internet community. Development is led by Duane Wessels of the | |
e25c139f | 13 | * National Laboratory for Applied Network Research and funded by the |
14 | * National Science Foundation. Squid is Copyrighted (C) 1998 by | |
15 | * Duane Wessels and the University of California San Diego. Please | |
16 | * see the COPYRIGHT file for full details. Squid incorporates | |
17 | * software developed and/or copyrighted by other sources. Please see | |
18 | * the CREDITS file for full details. | |
fab463b4 | 19 | * |
20 | * This program is free software; you can redistribute it and/or modify | |
21 | * it under the terms of the GNU General Public License as published by | |
22 | * the Free Software Foundation; either version 2 of the License, or | |
23 | * (at your option) any later version. | |
24 | * | |
25 | * This program is distributed in the hope that it will be useful, | |
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
28 | * GNU General Public License for more details. | |
29 | * | |
30 | * You should have received a copy of the GNU General Public License | |
31 | * along with this program; if not, write to the Free Software | |
cbdec147 | 32 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
e25c139f | 33 | * |
fab463b4 | 34 | */ |
35 | ||
fab463b4 | 36 | |
6ffa5ad9 | 37 | #include "squid.h" |
6ffa5ad9 | 38 | |
e97f40f4 | 39 | #if USE_ICMP |
40 | ||
16b204c4 | 41 | #define S_ICMP_ECHO 1 |
674ac814 | 42 | #if ALLOW_SOURCE_PING |
16b204c4 | 43 | #define S_ICMP_ICP 2 |
674ac814 | 44 | #endif |
16b204c4 | 45 | #define S_ICMP_DOM 3 |
46 | ||
a4da5477 | 47 | static PF icmpRecv; |
d11d0d98 | 48 | static void icmpSend(pingerEchoData * pkt, int len); |
674ac814 | 49 | #if ALLOW_SOURCE_PING |
ea3a2a69 | 50 | static void icmpHandleSourcePing(const struct sockaddr_in *from, const char *buf); |
674ac814 | 51 | #endif |
6ffa5ad9 | 52 | |
16b204c4 | 53 | static void |
0ee4272b | 54 | icmpSendEcho(struct in_addr to, int opcode, const char *payload, int len) |
6ffa5ad9 | 55 | { |
67a53546 | 56 | static pingerEchoData pecho; |
9d90e665 | 57 | if (payload && len == 0) |
58 | len = strlen(payload); | |
d11d0d98 | 59 | pecho.to = to; |
60 | pecho.opcode = (unsigned char) opcode; | |
61 | pecho.psize = len; | |
62 | xmemcpy(pecho.payload, payload, len); | |
63 | icmpSend(&pecho, sizeof(pingerEchoData) - PINGER_PAYLOAD_SZ + len); | |
6ffa5ad9 | 64 | } |
65 | ||
16b204c4 | 66 | static void |
9d90e665 | 67 | icmpRecv(int unused1, void *unused2) |
6ffa5ad9 | 68 | { |
9d90e665 | 69 | int n; |
d63079b8 | 70 | static int fail_count = 0; |
9d90e665 | 71 | pingerReplyData preply; |
72 | static struct sockaddr_in F; | |
a4da5477 | 73 | commSetSelect(icmp_sock, COMM_SELECT_READ, icmpRecv, NULL, 0); |
e924600d | 74 | memset(&preply, '\0', sizeof(pingerReplyData)); |
886f2785 | 75 | Counter.syscalls.sock.recvfroms++; |
9d90e665 | 76 | n = recv(icmp_sock, |
77 | (char *) &preply, | |
78 | sizeof(pingerReplyData), | |
79 | 0); | |
365a4bce | 80 | if (n < 0) { |
aebbcd07 | 81 | debug(50, 1) ("icmpRecv: recv: %s\n", xstrerror()); |
6b800ede | 82 | if (++fail_count == 10 || errno == ECONNREFUSED) |
83 | icmpClose(); | |
365a4bce | 84 | return; |
85 | } | |
d1a43e28 | 86 | fail_count = 0; |
6759a5fb | 87 | if (n == 0) /* test probe from pinger */ |
365a4bce | 88 | return; |
9d90e665 | 89 | F.sin_family = AF_INET; |
90 | F.sin_addr = preply.from; | |
91 | F.sin_port = 0; | |
92 | switch (preply.opcode) { | |
16b204c4 | 93 | case S_ICMP_ECHO: |
94 | break; | |
674ac814 | 95 | #if ALLOW_SOURCE_PING |
16b204c4 | 96 | case S_ICMP_ICP: |
9d90e665 | 97 | icmpHandleSourcePing(&F, preply.payload); |
16b204c4 | 98 | break; |
674ac814 | 99 | #endif |
16b204c4 | 100 | case S_ICMP_DOM: |
9d90e665 | 101 | netdbHandlePingReply(&F, preply.hops, preply.rtt); |
16b204c4 | 102 | break; |
103 | default: | |
aebbcd07 | 104 | debug(37, 1) ("icmpRecv: Bad opcode: %d\n", (int) preply.opcode); |
16b204c4 | 105 | break; |
106 | } | |
6ffa5ad9 | 107 | } |
108 | ||
16b204c4 | 109 | static void |
d11d0d98 | 110 | icmpSend(pingerEchoData * pkt, int len) |
16b204c4 | 111 | { |
16b204c4 | 112 | int x; |
d11d0d98 | 113 | if (icmp_sock < 0) |
114 | return; | |
7df9a3b8 | 115 | x = send(icmp_sock, (char *) pkt, len, 0); |
d11d0d98 | 116 | if (x < 0) { |
117 | debug(50, 1) ("icmpSend: send: %s\n", xstrerror()); | |
118 | if (errno == ECONNREFUSED) { | |
119 | icmpClose(); | |
120 | return; | |
16b204c4 | 121 | } |
d11d0d98 | 122 | } else if (x != len) { |
123 | debug(37, 1) ("icmpSend: Wrote %d of %d bytes\n", x, len); | |
16b204c4 | 124 | } |
125 | } | |
126 | ||
674ac814 | 127 | #if ALLOW_SOURCE_PING |
e97f40f4 | 128 | static void |
0ee4272b | 129 | icmpHandleSourcePing(const struct sockaddr_in *from, const char *buf) |
e97f40f4 | 130 | { |
38619029 | 131 | const cache_key *key; |
e97f40f4 | 132 | icp_common_t header; |
0ee4272b | 133 | const char *url; |
3c0117c9 | 134 | xmemcpy(&header, buf, sizeof(icp_common_t)); |
e97f40f4 | 135 | url = buf + sizeof(icp_common_t); |
007b8be4 | 136 | key = icpGetCacheKey(url, (int) header.reqnum); |
5ad33356 | 137 | debug(37, 3) ("icmpHandleSourcePing: from %s, key '%s'\n", |
138 | inet_ntoa(from->sin_addr), storeKeyText(key)); | |
e97f40f4 | 139 | /* call neighborsUdpAck even if ping_status != PING_WAITING */ |
5ad33356 | 140 | neighborsUdpAck(key, &header, from); |
e97f40f4 | 141 | } |
674ac814 | 142 | #endif |
5942e8d4 | 143 | |
e97f40f4 | 144 | #endif /* USE_ICMP */ |
145 | ||
16b204c4 | 146 | void |
147 | icmpPing(struct in_addr to) | |
148 | { | |
e97f40f4 | 149 | #if USE_ICMP |
16b204c4 | 150 | icmpSendEcho(to, S_ICMP_ECHO, NULL, 0); |
e97f40f4 | 151 | #endif |
16b204c4 | 152 | } |
153 | ||
674ac814 | 154 | #if ALLOW_SOURCE_PING |
16b204c4 | 155 | void |
fe4e214f | 156 | icmpSourcePing(struct in_addr to, const icp_common_t * header, const char *url) |
16b204c4 | 157 | { |
e97f40f4 | 158 | #if USE_ICMP |
16b204c4 | 159 | char *payload; |
160 | int len; | |
161 | int ulen; | |
a3d5953d | 162 | debug(37, 3) ("icmpSourcePing: '%s'\n", url); |
16b204c4 | 163 | if ((ulen = strlen(url)) > MAX_URL) |
164 | return; | |
7021844c | 165 | payload = memAllocate(MEM_8K_BUF); |
16b204c4 | 166 | len = sizeof(icp_common_t); |
3c0117c9 | 167 | xmemcpy(payload, header, len); |
16b204c4 | 168 | strcpy(payload + len, url); |
169 | len += ulen + 1; | |
170 | icmpSendEcho(to, S_ICMP_ICP, payload, len); | |
3f6c0fb2 | 171 | memFree(MEM_8K_BUF, payload); |
e97f40f4 | 172 | #endif |
16b204c4 | 173 | } |
674ac814 | 174 | #endif |
16b204c4 | 175 | |
176 | void | |
0ee4272b | 177 | icmpDomainPing(struct in_addr to, const char *domain) |
16b204c4 | 178 | { |
e97f40f4 | 179 | #if USE_ICMP |
a3d5953d | 180 | debug(37, 3) ("icmpDomainPing: '%s'\n", domain); |
16b204c4 | 181 | icmpSendEcho(to, S_ICMP_DOM, domain, 0); |
e97f40f4 | 182 | #endif |
16b204c4 | 183 | } |
184 | ||
e97f40f4 | 185 | void |
186 | icmpOpen(void) | |
16b204c4 | 187 | { |
e97f40f4 | 188 | #if USE_ICMP |
a7c05555 | 189 | char *args[2]; |
190 | int x; | |
191 | int rfd; | |
192 | int wfd; | |
193 | args[0] = "(pinger)"; | |
194 | args[1] = NULL; | |
195 | x = ipcCreate(IPC_UDP_SOCKET, | |
196 | Config.Program.pinger, | |
197 | args, | |
198 | "Pinger Socket", | |
199 | &rfd, | |
200 | &wfd); | |
201 | if (x < 0) | |
16b204c4 | 202 | return; |
a7c05555 | 203 | assert(rfd == wfd); |
204 | icmp_sock = rfd; | |
a4da5477 | 205 | commSetSelect(icmp_sock, COMM_SELECT_READ, icmpRecv, NULL, 0); |
5c5783a2 | 206 | commSetTimeout(icmp_sock, -1, NULL, NULL); |
aebbcd07 | 207 | debug(29, 1) ("Pinger socket opened on FD %d\n", icmp_sock); |
e97f40f4 | 208 | #endif |
16b204c4 | 209 | } |
fab463b4 | 210 | |
e97f40f4 | 211 | void |
212 | icmpClose(void) | |
213 | { | |
214 | #if USE_ICMP | |
e924600d | 215 | if (icmp_sock < 0) |
216 | return; | |
aebbcd07 | 217 | debug(29, 1) ("Closing Pinger socket on FD %d\n", icmp_sock); |
e97f40f4 | 218 | comm_close(icmp_sock); |
e97f40f4 | 219 | icmp_sock = -1; |
e97f40f4 | 220 | #endif |
221 | } |