]>
Commit | Line | Data |
---|---|---|
cc192b50 | 1 | /* |
262a0e14 | 2 | * $Id$ |
cc192b50 | 3 | * |
4 | * DEBUG: section 42 ICMP Pinger program | |
5 | * AUTHOR: Duane Wessels, Amos Jeffries | |
6 | * | |
7 | * SQUID Web Proxy Cache http://www.squid-cache.org/ | |
8 | * ---------------------------------------------------------- | |
9 | * | |
10 | * Squid is the result of efforts by numerous individuals from | |
11 | * the Internet community; see the CONTRIBUTORS file for full | |
12 | * details. Many organizations have provided support for Squid's | |
13 | * development; see the SPONSORS file for full details. Squid is | |
14 | * Copyrighted (C) 2001 by the Regents of the University of | |
15 | * California; see the COPYRIGHT file for full details. Squid | |
16 | * incorporates software developed and/or copyrighted by other | |
17 | * sources; see the CREDITS file for full details. | |
18 | * | |
19 | * This program is free software; you can redistribute it and/or modify | |
20 | * it under the terms of the GNU General Public License as published by | |
21 | * the Free Software Foundation; either version 2 of the License, or | |
22 | * (at your option) any later version. | |
26ac0430 | 23 | * |
cc192b50 | 24 | * This program is distributed in the hope that it will be useful, |
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
27 | * GNU General Public License for more details. | |
26ac0430 | 28 | * |
cc192b50 | 29 | * You should have received a copy of the GNU General Public License |
30 | * along with this program; if not, write to the Free Software | |
31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. | |
32 | * | |
33 | */ | |
34 | //#define SQUID_HELPER 1 | |
35 | ||
582c2af2 | 36 | #include "squid.h" |
cc192b50 | 37 | |
38 | #if USE_ICMP | |
39 | ||
582c2af2 | 40 | #include "leakcheck.h" |
cc192b50 | 41 | #include "SquidTime.h" |
b826ffb5 AJ |
42 | #include "Icmp4.h" |
43 | #include "IcmpPinger.h" | |
cc192b50 | 44 | #include "Debug.h" |
45 | ||
26ac0430 AJ |
46 | const char *icmpPktStr[] = { |
47 | "Echo Reply", | |
48 | "ICMP 1", | |
49 | "ICMP 2", | |
50 | "Destination Unreachable", | |
51 | "Source Quench", | |
52 | "Redirect", | |
53 | "ICMP 6", | |
54 | "ICMP 7", | |
55 | "Echo", | |
56 | "ICMP 9", | |
57 | "ICMP 10", | |
58 | "Time Exceeded", | |
59 | "Parameter Problem", | |
60 | "Timestamp", | |
61 | "Timestamp Reply", | |
62 | "Info Request", | |
63 | "Info Reply", | |
64 | "Out of Range Type" | |
65 | }; | |
cc192b50 | 66 | |
b826ffb5 | 67 | Icmp4::Icmp4() : Icmp() |
26ac0430 AJ |
68 | { |
69 | ; | |
cc192b50 | 70 | } |
71 | ||
b826ffb5 | 72 | Icmp4::~Icmp4() |
cc192b50 | 73 | { |
74 | Close(); | |
75 | } | |
76 | ||
77 | int | |
b826ffb5 | 78 | Icmp4::Open(void) |
cc192b50 | 79 | { |
80 | icmp_sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP); | |
81 | ||
82 | if (icmp_sock < 0) { | |
fa84c01d | 83 | debugs(50, DBG_CRITICAL, HERE << " icmp_sock: " << xstrerror()); |
cc192b50 | 84 | return -1; |
85 | } | |
86 | ||
87 | icmp_ident = getpid() & 0xffff; | |
e0236918 | 88 | debugs(42, DBG_IMPORTANT, "pinger: ICMP socket opened."); |
cc192b50 | 89 | |
90 | return icmp_sock; | |
91 | } | |
92 | ||
93 | void | |
b7ac5457 | 94 | Icmp4::SendEcho(Ip::Address &to, int opcode, const char *payload, int len) |
cc192b50 | 95 | { |
96 | int x; | |
97 | LOCAL_ARRAY(char, pkt, MAX_PKT4_SZ); | |
98 | ||
99 | struct icmphdr *icmp = NULL; | |
100 | icmpEchoData *echo; | |
101 | size_t icmp_pktsize = sizeof(struct icmphdr); | |
102 | struct addrinfo *S = NULL; | |
103 | ||
104 | memset(pkt, '\0', MAX_PKT4_SZ); | |
105 | ||
106 | icmp = (struct icmphdr *) (void *) pkt; | |
107 | ||
108 | /* | |
109 | * cevans - beware signed/unsigned issues in untrusted data from | |
110 | * the network!! | |
111 | */ | |
26ac0430 | 112 | if (len < 0) { |
cc192b50 | 113 | len = 0; |
114 | } | |
115 | ||
116 | // Construct ICMP packet header | |
117 | icmp->icmp_type = ICMP_ECHO; | |
118 | icmp->icmp_code = 0; | |
119 | icmp->icmp_cksum = 0; | |
120 | icmp->icmp_id = icmp_ident; | |
aec55359 FC |
121 | icmp->icmp_seq = (unsigned short) icmp_pkts_sent; |
122 | ++icmp_pkts_sent; | |
cc192b50 | 123 | |
124 | // Construct ICMP packet data content | |
125 | echo = (icmpEchoData *) (icmp + 1); | |
126 | echo->opcode = (unsigned char) opcode; | |
c3c6695b | 127 | memcpy(&echo->tv, ¤t_time, sizeof(struct timeval)); |
cc192b50 | 128 | |
129 | icmp_pktsize += sizeof(struct timeval) + sizeof(char); | |
130 | ||
26ac0430 | 131 | if (payload) { |
cc192b50 | 132 | if (len > MAX_PAYLOAD) |
133 | len = MAX_PAYLOAD; | |
134 | ||
41d00cd3 | 135 | memcpy(echo->payload, payload, len); |
cc192b50 | 136 | |
137 | icmp_pktsize += len; | |
138 | } | |
139 | ||
f45dd259 | 140 | icmp->icmp_cksum = CheckSum((unsigned short *) icmp, icmp_pktsize); |
cc192b50 | 141 | |
142 | to.GetAddrInfo(S); | |
143 | ((sockaddr_in*)S->ai_addr)->sin_port = 0; | |
144 | assert(icmp_pktsize <= MAX_PKT4_SZ); | |
145 | ||
30c48b1a | 146 | debugs(42, 5, HERE << "Send ICMP packet to " << to << "."); |
cc192b50 | 147 | |
148 | x = sendto(icmp_sock, | |
26ac0430 AJ |
149 | (const void *) pkt, |
150 | icmp_pktsize, | |
151 | 0, | |
152 | S->ai_addr, | |
153 | S->ai_addrlen); | |
cc192b50 | 154 | |
26ac0430 | 155 | if (x < 0) { |
e0236918 | 156 | debugs(42, DBG_IMPORTANT, HERE << "Error sending to ICMP packet to " << to << ". ERR: " << xstrerror()); |
cc192b50 | 157 | } |
158 | ||
159 | Log(to, ' ', NULL, 0, 0); | |
160 | } | |
161 | ||
162 | void | |
b826ffb5 | 163 | Icmp4::Recv(void) |
cc192b50 | 164 | { |
165 | int n; | |
166 | struct addrinfo *from = NULL; | |
167 | int iphdrlen = sizeof(iphdr); | |
168 | struct iphdr *ip = NULL; | |
169 | struct icmphdr *icmp = NULL; | |
170 | static char *pkt = NULL; | |
171 | struct timeval now; | |
172 | icmpEchoData *echo; | |
173 | static pingerReplyData preply; | |
174 | ||
26ac0430 | 175 | if (icmp_sock < 0) { |
fa84c01d | 176 | debugs(42, DBG_CRITICAL, HERE << "No socket! Recv() should not be called."); |
cc192b50 | 177 | return; |
178 | } | |
179 | ||
180 | if (pkt == NULL) | |
181 | pkt = (char *)xmalloc(MAX_PKT4_SZ); | |
182 | ||
183 | preply.from.InitAddrInfo(from); | |
184 | n = recvfrom(icmp_sock, | |
185 | (void *)pkt, | |
186 | MAX_PKT4_SZ, | |
187 | 0, | |
188 | from->ai_addr, | |
189 | &from->ai_addrlen); | |
190 | ||
191 | preply.from = *from; | |
192 | ||
193 | #if GETTIMEOFDAY_NO_TZP | |
194 | ||
195 | gettimeofday(&now); | |
196 | ||
197 | #else | |
198 | ||
199 | gettimeofday(&now, NULL); | |
200 | ||
201 | #endif | |
202 | ||
203 | debugs(42, 8, HERE << n << " bytes from " << preply.from); | |
204 | ||
205 | ip = (struct iphdr *) (void *) pkt; | |
206 | ||
207 | #if HAVE_STRUCT_IPHDR_IP_HL | |
208 | ||
209 | iphdrlen = ip->ip_hl << 2; | |
210 | ||
211 | #else /* HAVE_STRUCT_IPHDR_IP_HL */ | |
212 | #if WORDS_BIGENDIAN | |
213 | ||
214 | iphdrlen = (ip->ip_vhl >> 4) << 2; | |
215 | ||
216 | #else | |
217 | ||
218 | iphdrlen = (ip->ip_vhl & 0xF) << 2; | |
219 | ||
220 | #endif | |
221 | #endif /* HAVE_STRUCT_IPHDR_IP_HL */ | |
222 | ||
223 | icmp = (struct icmphdr *) (void *) (pkt + iphdrlen); | |
224 | ||
225 | if (icmp->icmp_type != ICMP_ECHOREPLY) | |
226 | return; | |
227 | ||
228 | if (icmp->icmp_id != icmp_ident) | |
229 | return; | |
230 | ||
231 | echo = (icmpEchoData *) (void *) (icmp + 1); | |
232 | ||
233 | preply.opcode = echo->opcode; | |
234 | ||
235 | preply.hops = ipHops(ip->ip_ttl); | |
236 | ||
c3c6695b | 237 | struct timeval tv; |
238 | memcpy(&tv, &echo->tv, sizeof(struct timeval)); | |
239 | preply.rtt = tvSubMsec(tv, now); | |
cc192b50 | 240 | |
241 | preply.psize = n - iphdrlen - (sizeof(icmpEchoData) - MAX_PKT4_SZ); | |
242 | ||
243 | control.SendResult(preply, (sizeof(pingerReplyData) - MAX_PKT4_SZ + preply.psize) ); | |
244 | ||
245 | Log(preply.from, icmp->icmp_type, icmpPktStr[icmp->icmp_type], preply.rtt, preply.hops); | |
246 | } | |
247 | ||
248 | #endif /* USE_ICMP */ |