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