modules/up/src/Core/network/ICMProbe.cc
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- icmprobeTimerHandler
- ICMProbe
- ICMProbe
- send
- handleTimer
- receive
1 //
2 // $Id: ICMProbe.cc,v 1.1.1.1 2000/03/10 16:32:19 engin Exp $
3 //
4 // Author(s): Ramesh Govindan
5
6 #ifdef HAVE_CONFIG_H
7 #include <config.h>
8 #endif
9
10 extern "C" {
11 #include <sys/types.h>
12 #include <netinet/in_systm.h>
13 #include <netinet/in.h>
14 #include <netinet/ip.h>
15 }
16
17 #include "util/Types.hh"
18 #include "util/Trail.hh"
19 #include "util/Handler.hh"
20 #include "util/Buffer.hh"
21 #include "sys/File.hh"
22 #include "sys/Pipe.hh"
23 #include "sys/Time.hh"
24 #include "sched/Timer.hh"
25 #include "sched/Dispatcher.hh"
26
27 #include "network/ICMProbe.hh"
28 #include "network/Headers.hh"
29 #include "network/Network.hh"
30
31 // Constants
32 static const unsigned char UDPProtocol = 17;
33
34 // Locals
35 static TraceCode traceICMProbe("net");
36 static TimeShort maxWait(10, 0);
37 static unsigned int probeNumber = 0x80000000;
38
39 static void
40 icmprobeTimerHandler(void* ptr,
/* [<][>][^][v][top][bottom][index][help] */
41 void*)
42 {
43 ((ICMProbe*) ptr)->handleTimer();
44 }
45
46 ICMProbe::ICMProbe(Address* a,
/* [<][>][^][v][top][bottom][index][help] */
47 Handler& cb,
48 int hc,
49 Address* v)
50 : ListNode()
51 {
52 done = cb;
53 to = *a;
54 hopcount = hc;
55 if (v) {
56 via = *v;
57 }
58 timer = NULL;
59 result = ICMProbeResultNone;
60 residualHops = 0;
61 network->pendingICMProbes.append(this);
62 probeId = 0;
63 lastRtt = InfiniteInterval;
64 sent = 0;
65 }
66
67 ICMProbe::~ICMProbe()
/* [<][>][^][v][top][bottom][index][help] */
68 {
69 network->pendingICMProbes.remove(this);
70 if (timer) {
71 delete timer;
72 }
73 }
74
75 void
76 ICMProbe::send()
/* [<][>][^][v][top][bottom][index][help] */
77 {
78 Handler th(icmprobeTimerHandler, this);
79 Handler nh(NULL, NULL);
80 Buffer* buf;
81 IP* ip;
82 IPOptLSRR* ipopt;
83 ICMP* icmp;
84 RawSocket* raw;
85 U32* t;
86 TimeLong at;
87 Address srcaddr;
88
89 responder.set(0);
90 result = ICMProbeResultNone;
91 sent++;
92 network->icmprobesSent++;
93
94 // Send packet
95 raw = new RawSocket(nh, nh, RawSocketICMP);
96 if (via.get()) {
97 buf = new Buffer(sizeof(IP) + sizeof(IPOptLSRR) + sizeof(ICMP) + 8);
98 } else {
99 buf = new Buffer(sizeof(IP) + sizeof(ICMP) + 8);
100 }
101 buf->zeroFill();
102
103 ip = (IP*) buf->contents;
104 ip->headerLength = via.get() ?
105 (sizeof(IP) + sizeof(IPOptLSRR)) >> 2 :
106 sizeof(IP) >> 2;
107 ip->version = 4;
108 ip->typeOfService = 0;
109 ip->totalLength = (ip->headerLength << 2) + sizeof(ICMP);
110 ip->identifier = 0;
111 ip->fragmentOffset = 0;
112 ip->timeToLive = hopcount;
113 ip->protocol = IPPROTO_ICMP;
114 ip->source = (network->interfaces.head())->address.get();
115 ip->destination = (via.get()) ? via.get() : to.get();
116 ip->hton();
117 ip->checksum = 0;
118 ip->checksum = network->cksum((U16*) ip, ip->headerLength << 2);
119
120 if (via.get()) {
121 IPOptLSRR* lsrr;
122
123 lsrr = (IPOptLSRR*) (ip + 1);
124 lsrr->nullopt = IPOPT_NOP;
125 lsrr->lsrropt = IPOPT_LSRR;
126 lsrr->length = sizeof(U32) + 3;
127 lsrr->pointer = IPOPT_MINOFF;
128 lsrr->gateway = to.get();
129 lsrr->hton();
130 icmp = (ICMP*) (lsrr + 1);
131 } else {
132 icmp = (ICMP*) (ip + 1);
133 }
134
135 ASSERT(probeNumber != 0xffffffff); // Wrap around
136 probeNumber++;
137 probeId = probeNumber;
138
139 icmp->type = ICMPTypeEcho;
140 icmp->code = 0;
141 icmp->gateway = probeNumber;
142 icmp->hton();
143 icmp->checksum = 0;
144 icmp->checksum = network->cksum((U16*) icmp, sizeof(ICMP) + 8);
145
146 dispatcher.systemClock.sync();
147 sentAt = dispatcher.systemClock;
148
149 raw->sendTo(buf->contents, buf->size, to, 0);
150
151 TRACE(traceICMProbe, "icmprobe to %s:%d\n", to.name(), hopcount);
152
153 delete raw;
154 delete buf;
155
156 if (timer) {
157 delete timer;
158 }
159 at = dispatcher.systemClock;
160 at = at + maxWait;
161 timer = new Timer(th, at);
162
163 return;
164 }
165
166 void
167 ICMProbe::handleTimer()
/* [<][>][^][v][top][bottom][index][help] */
168 {
169 TRACE(traceICMProbe, "icmprobe failed to %s\n", to.name());
170
171 timer = NULL;
172 network->icmprobesTimedOut++;
173 done.callBack((void*) this);
174 lastRtt = InfiniteInterval;
175 return;
176 }
177
178 Boolean
179 ICMProbe::receive(IP* ip)
/* [<][>][^][v][top][bottom][index][help] */
180 {
181 ICMP* icmp;
182 unsigned short sum;
183 IP* iip;
184 int datalen;
185
186 // Verify signature to see if it is for us
187 icmp = (struct ICMP*) ((char*) ip + (ip->headerLength << 2));
188 if (icmp->type != ICMPTypeTimeExceeded &&
189 icmp->type != ICMPTypeDestinationUnreachable &&
190 icmp->type != ICMPTypeEchoReply)
191 return false;
192
193 if (icmp->type == ICMPTypeTimeExceeded ||
194 icmp->type == ICMPTypeDestinationUnreachable) {
195
196 datalen = ip->totalLength - (ip->headerLength << 2) - sizeof(ICMP);
197 if (datalen < sizeof(IP))
198 return false; // Malformed response, discard
199
200 iip = (struct IP*) (icmp + 1);
201 iip->ntoh();
202
203 if (datalen < ((iip->headerLength << 2) + 2 * sizeof(unsigned long)))
204 return false; // Timestamp not there, discard
205
206 if (iip->destination != to.get())
207 return false;
208
209 ICMP* icmpi = (ICMP*) (((char*) iip) + (iip->headerLength<<2));
210 icmpi->ntoh();
211
212 if (icmpi->gateway != probeNumber) // it is not the pkt we sent
213 return false;
214 }
215
216 dispatcher.systemClock.sync();
217 lastRtt = dispatcher.systemClock - sentAt;
218
219 switch (icmp->type) {
220 case ICMPTypeEchoReply:
221 if (ip->source != to.get()) {
222 return false;
223 }
224 if (icmp->gateway != probeNumber) {
225 return false;
226 }
227
228 responder.set(ip->source);
229 residualHops = 0;
230 result = ICMProbeResultReachedNode;
231
232 TRACE(traceICMProbe, "received icmprobe for %s:%d from %s\n",
233 to.name(), hopcount, responder.name());
234 done.callBack((void*) this);
235 break;
236
237 case ICMPTypeTimeExceeded:
238 if (iip->timeToLive <= 1) {
239 responder.set(ip->source);
240 result = ICMProbeResultTimeExpired;
241 TRACE(traceICMProbe, "received icmprobe for %s:%d from %s\n",
242 to.name(), hopcount, responder.name());
243 } else {
244 responder.set(ip->source);
245 ERROR("unexpected ttl %d in ICMP TimeExceeded from %s\n",
246 iip->timeToLive, responder.name());
247 result = ICMProbeResultDontCare;
248 }
249 done.callBack((void*) this);
250 break;
251
252 case ICMPTypeDestinationUnreachable:
253 residualHops = iip->timeToLive;
254 responder.set(ip->source);
255 switch (icmp->code) {
256 case ICMPUnreachNet:
257 case ICMPUnreachHost:
258 result = ICMProbeResultUnreachable;
259 break;
260
261 case ICMPUnreachProto:
262 case ICMPUnreachPort:
263 result = ICMProbeResultReachedNode;
264 break;
265
266 case ICMPUnreachSrtFail:
267 result = ICMProbeResultSourceRouteFailed;
268 break;
269
270 case ICMPUnreachNeedFrag:
271 default:
272 result = ICMProbeResultDontCare;
273 break;
274 }
275 TRACE(traceICMProbe, "received icmprobe for %s:%d from %s\n",
276 to.name(), hopcount, responder.name());
277 done.callBack((void*) this);
278 // FallThrough
279
280 default:
281 break;
282 }
283 return true;
284 }
285
286 // Copyright (c) 1994 by the University of Southern California.
287 // All rights reserved.
288 //
289 // Permission to use, copy, modify, and distribute this software and
290 // its documentation in source and binary forms for lawful
291 // non-commercial purposes and without fee is hereby granted, provided
292 // that the above copyright notice appear in all copies and that both
293 // the copyright notice and this permission notice appear in supporting
294 // documentation, and that any documentation, advertising materials,
295 // and other materials related to such distribution and use acknowledge
296 // that the software was developed by the University of Southern
297 // California and/or Information Sciences Institute.
298 // The name of the University of Southern California may not
299 // be used to endorse or promote products derived from this software
300 // without specific prior written permission.
301 //
302 // THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY REPRESENTATIONS
303 // ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. THIS SOFTWARE IS
304 // PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
305 // INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
306 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
307 // NON-INFRINGEMENT.
308 //
309 // IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
310 // SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
311 // TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
312 // THE USE OR PERFORMANCE OF THIS SOFTWARE.
313 //
314 // Questions concerning this software should be directed to
315 // scan@isi.edu.
316 //
317
318