]>
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) { | |
82 | debugs(50, 0, HERE << " icmp_sock: " << xstrerror()); | |
83 | return -1; | |
84 | } | |
85 | ||
86 | icmp_ident = getpid() & 0xffff; | |
87 | debugs(42, 1, "pinger: ICMP socket opened."); | |
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; | |
f45dd259 | 120 | icmp->icmp_seq = (unsigned short) 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) { |
cc192b50 | 154 | debugs(42, 1, HERE << "Error sending to ICMP packet to " << to << ". ERR: " << xstrerror()); |
155 | } | |
156 | ||
157 | Log(to, ' ', NULL, 0, 0); | |
158 | } | |
159 | ||
160 | void | |
b826ffb5 | 161 | Icmp4::Recv(void) |
cc192b50 | 162 | { |
163 | int n; | |
164 | struct addrinfo *from = NULL; | |
165 | int iphdrlen = sizeof(iphdr); | |
166 | struct iphdr *ip = NULL; | |
167 | struct icmphdr *icmp = NULL; | |
168 | static char *pkt = NULL; | |
169 | struct timeval now; | |
170 | icmpEchoData *echo; | |
171 | static pingerReplyData preply; | |
172 | ||
26ac0430 | 173 | if (icmp_sock < 0) { |
cc192b50 | 174 | debugs(42, 0, HERE << "No socket! Recv() should not be called."); |
175 | return; | |
176 | } | |
177 | ||
178 | if (pkt == NULL) | |
179 | pkt = (char *)xmalloc(MAX_PKT4_SZ); | |
180 | ||
181 | preply.from.InitAddrInfo(from); | |
182 | n = recvfrom(icmp_sock, | |
183 | (void *)pkt, | |
184 | MAX_PKT4_SZ, | |
185 | 0, | |
186 | from->ai_addr, | |
187 | &from->ai_addrlen); | |
188 | ||
189 | preply.from = *from; | |
190 | ||
191 | #if GETTIMEOFDAY_NO_TZP | |
192 | ||
193 | gettimeofday(&now); | |
194 | ||
195 | #else | |
196 | ||
197 | gettimeofday(&now, NULL); | |
198 | ||
199 | #endif | |
200 | ||
201 | debugs(42, 8, HERE << n << " bytes from " << preply.from); | |
202 | ||
203 | ip = (struct iphdr *) (void *) pkt; | |
204 | ||
205 | #if HAVE_STRUCT_IPHDR_IP_HL | |
206 | ||
207 | iphdrlen = ip->ip_hl << 2; | |
208 | ||
209 | #else /* HAVE_STRUCT_IPHDR_IP_HL */ | |
210 | #if WORDS_BIGENDIAN | |
211 | ||
212 | iphdrlen = (ip->ip_vhl >> 4) << 2; | |
213 | ||
214 | #else | |
215 | ||
216 | iphdrlen = (ip->ip_vhl & 0xF) << 2; | |
217 | ||
218 | #endif | |
219 | #endif /* HAVE_STRUCT_IPHDR_IP_HL */ | |
220 | ||
221 | icmp = (struct icmphdr *) (void *) (pkt + iphdrlen); | |
222 | ||
223 | if (icmp->icmp_type != ICMP_ECHOREPLY) | |
224 | return; | |
225 | ||
226 | if (icmp->icmp_id != icmp_ident) | |
227 | return; | |
228 | ||
229 | echo = (icmpEchoData *) (void *) (icmp + 1); | |
230 | ||
231 | preply.opcode = echo->opcode; | |
232 | ||
233 | preply.hops = ipHops(ip->ip_ttl); | |
234 | ||
c3c6695b | 235 | struct timeval tv; |
236 | memcpy(&tv, &echo->tv, sizeof(struct timeval)); | |
237 | preply.rtt = tvSubMsec(tv, now); | |
cc192b50 | 238 | |
239 | preply.psize = n - iphdrlen - (sizeof(icmpEchoData) - MAX_PKT4_SZ); | |
240 | ||
241 | control.SendResult(preply, (sizeof(pingerReplyData) - MAX_PKT4_SZ + preply.psize) ); | |
242 | ||
243 | Log(preply.from, icmp->icmp_type, icmpPktStr[icmp->icmp_type], preply.rtt, preply.hops); | |
244 | } | |
245 | ||
246 | #endif /* USE_ICMP */ |