## modules/up/src/Core/network/TProbe.cc

/* [<][>][^][v][top][bottom][index][help] */

## FUNCTIONS

This source file includes following functions.

1. tprobeTimerHandler
2. TProbe
3. TProbe
4. send
5. handleTimer
6. 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

/* [<][>][^][v][top][bottom][index][help] */