]> git.ipfire.org Git - thirdparty/squid.git/blame - src/icmp.cc
NO_CACHE_DIGEST_DIRECT is unused
[thirdparty/squid.git] / src / icmp.cc
CommitLineData
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 47static PF icmpRecv;
d11d0d98 48static void icmpSend(pingerEchoData * pkt, int len);
674ac814 49#if ALLOW_SOURCE_PING
ea3a2a69 50static void icmpHandleSourcePing(const struct sockaddr_in *from, const char *buf);
674ac814 51#endif
6ffa5ad9 52
16b204c4 53static void
0ee4272b 54icmpSendEcho(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 66static void
9d90e665 67icmpRecv(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 109static void
d11d0d98 110icmpSend(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 128static void
0ee4272b 129icmpHandleSourcePing(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 146void
147icmpPing(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 155void
fe4e214f 156icmpSourcePing(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
176void
0ee4272b 177icmpDomainPing(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 185void
186icmpOpen(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 211void
212icmpClose(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}