modules/up/src/Core/network/TProbe.cc
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- tprobeTimerHandler
- TProbe
- TProbe
- send
- handleTimer
- receive
1 //
2 // $Id: TProbe.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/TProbe.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 traceTProbe("net");
36 static TimeShort maxWait(10, 0);
37 static unsigned int probeNumber = 0x80000000;
38
39 static void
40 tprobeTimerHandler(void* ptr,
/* [<][>][^][v][top][bottom][index][help] */
41 void*)
42 {
43 ((TProbe*) ptr)->handleTimer();
44 }
45
46 TProbe::TProbe(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 = TProbeResultNone;
60 residualHops = 0;
61 network->pendingTProbes.append(this);
62 probeId = 0;
63 lastRtt = InfiniteInterval;
64 sent = 0;
65 }
66
67 TProbe::~TProbe()
/* [<][>][^][v][top][bottom][index][help] */
68 {
69 network->pendingTProbes.remove(this);
70 if (timer) {
71 delete timer;
72 }
73 }
74
75 void
76 TProbe::send()
/* [<][>][^][v][top][bottom][index][help] */
77 {
78 Handler th(tprobeTimerHandler, this);
79 Handler nh(NULL, NULL);
80 Buffer* buf;
81 IP* ip;
82 IPOptLSRR* ipopt;
83 UDP* udp;
84 RawSocket* raw;
85 U32* t;
86 TimeLong at;
87 Address srcaddr;
88
89 responder.set(0);
90 result = TProbeResultNone;
91 sent++;
92 network->tprobesSent++;
93
94 // Send packet
95 raw = new RawSocket(nh, nh, RawSocketICMP);
96 if (via.get()) {
97 buf = new Buffer(sizeof(IP) + sizeof(IPOptLSRR) + sizeof(UDP));
98 } else {
99 buf = new Buffer(sizeof(IP) + sizeof(UDP));
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(UDP);
110 ip->identifier = 0;
111 ip->fragmentOffset = 0;
112 ip->timeToLive = hopcount;
113 ip->protocol = UDPProtocol;
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,
119 ip->headerLength << 2);
120
121 if (via.get()) {
122 IPOptLSRR* lsrr;
123
124 lsrr = (IPOptLSRR*) (ip + 1);
125 lsrr->nullopt = IPOPT_NOP;
126 lsrr->lsrropt = IPOPT_LSRR;
127 lsrr->length = sizeof(U32) + 3;
128 lsrr->pointer = IPOPT_MINOFF;
129 lsrr->gateway = to.get();
130 lsrr->hton();
131 udp = (UDP*) (lsrr + 1);
132 } else {
133 udp = (UDP*) (ip + 1);
134 }
135
136 ASSERT(probeNumber != 0xffffffff); // Wrap around
137 probeNumber++;
138 probeId = probeNumber;
139
140 udp->sourcePort = ((unsigned int) probeId) & 0xffff;
141 udp->destinationPort = (((unsigned int) probeId >> 16) & 0xffff);
142 ASSERT(udp->destinationPort & 0x8000);
143 udp->length = sizeof(UDP);
144 udp->hton();
145 udp->checksum = 0;
146
147 dispatcher.systemClock.sync();
148 sentAt = dispatcher.systemClock;
149
150 raw->sendTo(buf->contents, buf->size, to, 0);
151
152 TRACE(traceTProbe, "tprobe to %s:%d\n", to.name(), hopcount);
153
154 delete raw;
155 delete buf;
156
157 if (timer) {
158 delete timer;
159 }
160 at = dispatcher.systemClock;
161 at = at + maxWait;
162 timer = new Timer(th, at);
163
164 return;
165 }
166
167 void
168 TProbe::handleTimer()
/* [<][>][^][v][top][bottom][index][help] */
169 {
170 TRACE(traceTProbe, "tprobe failed to %s\n", to.name());
171
172 timer = NULL;
173 network->tprobesTimedOut++;
174 done.callBack((void*) this);
175 lastRtt = InfiniteInterval;
176 return;
177 }
178
179 Boolean
180 TProbe::receive(IP* ip)
/* [<][>][^][v][top][bottom][index][help] */
181 {
182 ICMP* icmp;
183 UDP* udp;
184 unsigned short sum;
185 IP* iip;
186 int datalen;
187
188 // Verify signature to see if it is for us
189 icmp = (struct ICMP*) ((char*) ip + (ip->headerLength << 2));
190 if (icmp->type != ICMPTypeTimeExceeded &&
191 icmp->type != ICMPTypeDestinationUnreachable) {
192 return false;
193 }
194
195 datalen = ip->totalLength - (ip->headerLength << 2) - sizeof(ICMP);
196 if (datalen < sizeof(IP)) {
197 return false; // Malformed response, discard
198 }
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
207 if (iip->destination != to.get()) {
208 return false;
209 }
210
211 udp = (UDP*) (((char*) iip) + (iip->headerLength<<2));
212 udp->ntoh();
213
214 if (udp->sourcePort != (((unsigned int) probeId) & 0xffff)) {
215 return false;
216 }
217
218 if (udp->destinationPort != (((unsigned int) probeId >> 16) & 0xffff)) {
219 return false;
220 }
221
222 dispatcher.systemClock.sync();
223 lastRtt = dispatcher.systemClock - sentAt;
224
225 switch (icmp->type) {
226 case ICMPTypeTimeExceeded:
227 if (iip->timeToLive <= 1) {
228 responder.set(ip->source);
229 result = TProbeResultTimeExpired;
230 TRACE(traceTProbe, "received tprobe for %s:%d from %s\n",
231 to.name(), hopcount, responder.name());
232 } else {
233 responder.set(ip->source);
234 ERROR("unexpected ttl %d in ICMP TimeExceeded from %s\n",
235 iip->timeToLive, responder.name());
236 result = TProbeResultDontCare;
237 }
238 done.callBack((void*) this);
239 break;
240
241 case ICMPTypeDestinationUnreachable:
242 residualHops = iip->timeToLive;
243 responder.set(ip->source);
244 switch (icmp->code) {
245 case ICMPUnreachNet:
246 case ICMPUnreachHost:
247 result = TProbeResultUnreachable;
248 break;
249
250 case ICMPUnreachProto:
251 case ICMPUnreachPort:
252 result = TProbeResultReachedNode;
253 break;
254
255 case ICMPUnreachSrtFail:
256 result = TProbeResultSourceRouteFailed;
257 break;
258
259 case ICMPUnreachNeedFrag:
260 default:
261 result = TProbeResultDontCare;
262 break;
263 }
264 TRACE(traceTProbe, "received tprobe for %s:%d from %s\n",
265 to.name(), hopcount, responder.name());
266 done.callBack((void*) this);
267 // FallThrough
268
269 default:
270 break;
271 }
272 return true;
273 }
274
275 // Copyright (c) 1994 by the University of Southern California.
276 // All rights reserved.
277 //
278 // Permission to use, copy, modify, and distribute this software and
279 // its documentation in source and binary forms for lawful
280 // non-commercial purposes and without fee is hereby granted, provided
281 // that the above copyright notice appear in all copies and that both
282 // the copyright notice and this permission notice appear in supporting
283 // documentation, and that any documentation, advertising materials,
284 // and other materials related to such distribution and use acknowledge
285 // that the software was developed by the University of Southern
286 // California and/or Information Sciences Institute.
287 // The name of the University of Southern California may not
288 // be used to endorse or promote products derived from this software
289 // without specific prior written permission.
290 //
291 // THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY REPRESENTATIONS
292 // ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. THIS SOFTWARE IS
293 // PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
294 // INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
295 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
296 // NON-INFRINGEMENT.
297 //
298 // IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
299 // SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
300 // TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
301 // THE USE OR PERFORMANCE OF THIS SOFTWARE.
302 //
303 // Questions concerning this software should be directed to
304 // scan@isi.edu.
305 //
306
307