]>
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 | ||
f7f3304a | 36 | #include "squid-old.h" |
cc192b50 | 37 | |
38 | #if USE_ICMP | |
39 | ||
40 | #include "SquidTime.h" | |
b826ffb5 AJ |
41 | #include "Icmp4.h" |
42 | #include "IcmpPinger.h" | |
cc192b50 | 43 | #include "Debug.h" |
44 | ||
26ac0430 AJ |
45 | const char *icmpPktStr[] = { |
46 | "Echo Reply", | |
47 | "ICMP 1", | |
48 | "ICMP 2", | |
49 | "Destination Unreachable", | |
50 | "Source Quench", | |
51 | "Redirect", | |
52 | "ICMP 6", | |
53 | "ICMP 7", | |
54 | "Echo", | |
55 | "ICMP 9", | |
56 | "ICMP 10", | |
57 | "Time Exceeded", | |
58 | "Parameter Problem", | |
59 | "Timestamp", | |
60 | "Timestamp Reply", | |
61 | "Info Request", | |
62 | "Info Reply", | |
63 | "Out of Range Type" | |
64 | }; | |
cc192b50 | 65 | |
b826ffb5 | 66 | Icmp4::Icmp4() : Icmp() |
26ac0430 AJ |
67 | { |
68 | ; | |
cc192b50 | 69 | } |
70 | ||
b826ffb5 | 71 | Icmp4::~Icmp4() |
cc192b50 | 72 | { |
73 | Close(); | |
74 | } | |
75 | ||
76 | int | |
b826ffb5 | 77 | Icmp4::Open(void) |
cc192b50 | 78 | { |
79 | icmp_sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP); | |
80 | ||
81 | if (icmp_sock < 0) { | |
fa84c01d | 82 | debugs(50, DBG_CRITICAL, HERE << " icmp_sock: " << xstrerror()); |
cc192b50 | 83 | return -1; |
84 | } | |
85 | ||
86 | icmp_ident = getpid() & 0xffff; | |
e0236918 | 87 | debugs(42, DBG_IMPORTANT, "pinger: ICMP socket opened."); |
cc192b50 | 88 | |
89 | return icmp_sock; | |
90 | } | |
91 | ||
92 | void | |
b7ac5457 | 93 | Icmp4::SendEcho(Ip::Address &to, int opcode, const char *payload, int len) |
cc192b50 | 94 | { |
95 | int x; | |
96 | LOCAL_ARRAY(char, pkt, MAX_PKT4_SZ); | |
97 | ||
98 | struct icmphdr *icmp = NULL; | |
99 | icmpEchoData *echo; | |
100 | size_t icmp_pktsize = sizeof(struct icmphdr); | |
101 | struct addrinfo *S = NULL; | |
102 | ||
103 | memset(pkt, '\0', MAX_PKT4_SZ); | |
104 | ||
105 | icmp = (struct icmphdr *) (void *) pkt; | |
106 | ||
107 | /* | |
108 | * cevans - beware signed/unsigned issues in untrusted data from | |
109 | * the network!! | |
110 | */ | |
26ac0430 | 111 | if (len < 0) { |
cc192b50 | 112 | len = 0; |
113 | } | |
114 | ||
115 | // Construct ICMP packet header | |
116 | icmp->icmp_type = ICMP_ECHO; | |
117 | icmp->icmp_code = 0; | |
118 | icmp->icmp_cksum = 0; | |
119 | icmp->icmp_id = icmp_ident; | |
aec55359 FC |
120 | icmp->icmp_seq = (unsigned short) icmp_pkts_sent; |
121 | ++icmp_pkts_sent; | |
cc192b50 | 122 | |
123 | // Construct ICMP packet data content | |
124 | echo = (icmpEchoData *) (icmp + 1); | |
125 | echo->opcode = (unsigned char) opcode; | |
c3c6695b | 126 | memcpy(&echo->tv, ¤t_time, sizeof(struct timeval)); |
cc192b50 | 127 | |
128 | icmp_pktsize += sizeof(struct timeval) + sizeof(char); | |
129 | ||
26ac0430 | 130 | if (payload) { |
cc192b50 | 131 | if (len > MAX_PAYLOAD) |
132 | len = MAX_PAYLOAD; | |
133 | ||
41d00cd3 | 134 | memcpy(echo->payload, payload, len); |
cc192b50 | 135 | |
136 | icmp_pktsize += len; | |
137 | } | |
138 | ||
f45dd259 | 139 | icmp->icmp_cksum = CheckSum((unsigned short *) icmp, icmp_pktsize); |
cc192b50 | 140 | |
141 | to.GetAddrInfo(S); | |
142 | ((sockaddr_in*)S->ai_addr)->sin_port = 0; | |
143 | assert(icmp_pktsize <= MAX_PKT4_SZ); | |
144 | ||
30c48b1a | 145 | debugs(42, 5, HERE << "Send ICMP packet to " << to << "."); |
cc192b50 | 146 | |
147 | x = sendto(icmp_sock, | |
26ac0430 AJ |
148 | (const void *) pkt, |
149 | icmp_pktsize, | |
150 | 0, | |
151 | S->ai_addr, | |
152 | S->ai_addrlen); | |
cc192b50 | 153 | |
26ac0430 | 154 | if (x < 0) { |
e0236918 | 155 | debugs(42, DBG_IMPORTANT, HERE << "Error sending to ICMP packet to " << to << ". ERR: " << xstrerror()); |
cc192b50 | 156 | } |
157 | ||
158 | Log(to, ' ', NULL, 0, 0); | |
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 | ||
224 | if (icmp->icmp_type != ICMP_ECHOREPLY) | |
225 | return; | |
226 | ||
227 | if (icmp->icmp_id != icmp_ident) | |
228 | return; | |
229 | ||
230 | echo = (icmpEchoData *) (void *) (icmp + 1); | |
231 | ||
232 | preply.opcode = echo->opcode; | |
233 | ||
234 | preply.hops = ipHops(ip->ip_ttl); | |
235 | ||
c3c6695b | 236 | struct timeval tv; |
237 | memcpy(&tv, &echo->tv, sizeof(struct timeval)); | |
238 | preply.rtt = tvSubMsec(tv, now); | |
cc192b50 | 239 | |
240 | preply.psize = n - iphdrlen - (sizeof(icmpEchoData) - MAX_PKT4_SZ); | |
241 | ||
242 | control.SendResult(preply, (sizeof(pingerReplyData) - MAX_PKT4_SZ + preply.psize) ); | |
243 | ||
244 | Log(preply.from, icmp->icmp_type, icmpPktStr[icmp->icmp_type], preply.rtt, preply.hops); | |
245 | } | |
246 | ||
247 | #endif /* USE_ICMP */ |