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

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

## FUNCTIONS

This source file includes following functions.

1. netReadHandler
2. Interface
3. Interface
4. Network
5. Network
6. dump
7. receive
8. cksum

       1 //
       2 // $Id: Network.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 #include <cerrno>
      11
      12 extern "C" {
      13 #include <sys/types.h>
      14 #include <sys/socket.h>
      15 #include <net/if.h>
      16 #include <netinet/in.h>
      17 #include <arpa/inet.h>
      18 #include <sys/ioctl.h>
      19 };
      20
      21 #include "util/Types.hh"
      22 #include "util/Trail.hh"
      23 #include "util/Handler.hh"
      24 #include "util/Buffer.hh"
      25 #include "sys/File.hh"
      26 #include "sys/Pipe.hh"
      27 #include "sched/Job.hh"
      28 #include "sched/Dispatcher.hh"
      29
      30 #include "network/Ping.hh"
      31 #include "network/Prefix.hh"
      32 #include "network/Mtrace.hh"
      33 #include "network/Network.hh"
      34 #include "network/Headers.hh"
      35
      36 // Constants
      37 static const int        MaxBufferSize = 1024;
      38 static const int        MaxInterfaces = 32;
      39
      40 // File local
      41 static TraceCode        traceNetwork("network");
      42
      43 // Globals
      44 Network*        network = NULL;
      45
      46 static void
      47 netReadHandler(void* ptr,
         /* [<][>][^][v][top][bottom][index][help] */
      48                 void* arg)
      49 {
      50     ((Network*) ptr)->receive((RawSocket*) arg);
      51 }
      52
      53 Network::Interface::Interface(char* ifname,
         /* [<][>][^][v][top][bottom][index][help] */
      54                               U32 ifaddr)
      55         : ListNode()
      56 {
      57     name = strdup(ifname);
      58     address.set(ifaddr);
      59     TRACE(traceNetwork, "adding interface %s:%s\n", name, address.name());
      60 }
      61
      62 Network::Interface::~Interface()
         /* [<][>][^][v][top][bottom][index][help] */
      63 {
      64     TRACE(traceNetwork, "deleting interface %s:%s\n", name, address.name());
      65     free(name);
      66 }
      67
      68 Network::Network()
         /* [<][>][^][v][top][bottom][index][help] */
      69 {
      70     Handler             rh(netReadHandler, this);
      71     Handler             nh(NULL, NULL);
      72     struct sockaddr_in  sin;
      73     int                 socklen = sizeof(sin);
      74     int                 sock;
      75     struct ifconf       ifc;
      76     struct ifreq        ifrs[MaxInterfaces];
      77     struct ifreq        *ifr;
      78     Network::Interface* interface;
      79     U32                 addr;
      80     Address             group;
      81
      82     icmpSocket = new RawSocket(rh, nh, RawSocketICMP);
      83     igmpSocket = new RawSocket(rh, nh, RawSocketIGMP);
      84
      85     group.set(MtraceMulticast);
      86     igmpSocket->join(group);
      87     recvBuffer = new Buffer(MaxBufferSize);
      88
      89     // First find all interfaces
      90     if ((sock = ::socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
      91         FATAL("couldn't open socket for getting interfaces: %s\n",
      92               strerror(errno));
      93         // NotReached
      94     }
      95
      96     ifc.ifc_len = sizeof(struct ifreq) * MaxInterfaces;
      97     ifc.ifc_buf = (char*) &(ifrs[0]);
      98
      99     if (ioctl(sock, SIOCGIFCONF, (void*) &ifc) < 0) {
     100         FATAL("failed ioctl for getting interface list: %s\n",
     101               strerror(errno));
     102         // NotReached
     103     }
     104
     105     for (int i = 0; i < ifc.ifc_len; i++) {
     106         ifr = &(ifrs[i]);
     107         addr = ntohl(((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr);
     108         if (addr == 0) {
     109             break;
     110         }
     111         if (addr != INADDR_LOOPBACK) {
     112             interface = new Network::Interface(ifr->ifr_name, addr);
     113             interfaces.append(interface);
     114         }
     115     }
     116     close(sock);
     117
     118     if (interfaces.isEmpty()) {
     119         FATAL("couldn't find any usable interfaces\n");
     120         // NotReached
     121     }
     122
     123     tprobesSent = 0;
     124     tprobesTimedOut = 0;
     125     icmprobesSent = 0;
     126     icmprobesTimedOut = 0;
     127
     128     return;
     129 }
     130
     131 Network::~Network()
         /* [<][>][^][v][top][bottom][index][help] */
     132 {
     133     delete icmpSocket;
     134     delete igmpSocket;
     135     delete recvBuffer;
     136     interfaces.clear();
     137     pendingPings.clear();
     138     pendingTProbes.clear();
     139     pendingICMProbes.clear();
     140 }
     141
     142 void
     143 Network::dump(FILE* fp)
         /* [<][>][^][v][top][bottom][index][help] */
     144 {
     145     fprintf(fp, "tprobes sent %Lu timed-out %Lu\n",
     146             tprobesSent, tprobesTimedOut);
     147     fprintf(fp, "icmprobes sent %Lu timed-out %Lu\n",
     148             icmprobesSent, icmprobesTimedOut);
     149     return;
     150 }
     151
     152 void
     153 Network::receive(RawSocket* socket)
         /* [<][>][^][v][top][bottom][index][help] */
     154 {
     155     int         length;
     156     IP*         ip;
     157     ICMP*       icmp;
     158     IGMP*       igmp;
     159     U16         sum;
     160
     161     length = socket->read(recvBuffer->contents, recvBuffer->capacity);
     162     if (length < 0) {
     163         return;
     164     }
     165     ip = (IP*) recvBuffer->contents;
     166     ip->ntoh();
     167
     168     if (ip->totalLength != length) {
     169         return;
     170     }
     171
     172     if (length < (ip->headerLength << 2)) {
     173         return;
     174     }
     175     length -= ip->headerLength << 2;
     176
     177     switch (ip->protocol) {
     178         case IPPROTO_ICMP:
     179         {
     180             // Sanity check ICMP packet
     181             if (length < sizeof(ICMP)) {
     182                 return;
     183             }
     184
     185             icmp = (ICMP*) ((char*) ip + (ip->headerLength << 2));
     186             sum = icmp->checksum;
     187             icmp->checksum = 0;
     188             if (sum && (sum != network->cksum((U16*) icmp, length))) {
     189                 return;
     190             }
     191             icmp->ntoh();
     192
     193             // Farm out packet to whoever's waiting
     194             for (Ping* ping = pendingPings.head(); ping != NULL;
     195                  ping = pendingPings.next(ping)) {
     196                 if (ping->receive(ip)) {
     197                     break;
     198                 }
     199             }
     200             for (TProbe* tp = pendingTProbes.head(); tp != NULL;
     201                  tp = pendingTProbes.next(tp)) {
     202                 if (tp->receive(ip)) {
     203                     break;
     204                 }
     205             }
     206             for (ICMProbe* tp = pendingICMProbes.head(); tp != NULL;
     207                  tp = pendingICMProbes.next(tp)) {
     208                 if (tp->receive(ip)) {
     209                     break;
     210                 }
     211             }
     212             break;
     213         }
     214
     215         case IPPROTO_IGMP:
     216         {
     217             // Sanity check IGMP packet
     218             if (length < sizeof(IGMP)) {
     219                 return;
     220             }
     221
     222             igmp = (IGMP*) ((char*) ip + (ip->headerLength << 2));
     223             sum = igmp->checksum;
     224             igmp->checksum = 0;
     225             if (sum && (sum != network->cksum((U16*) igmp, length))) {
     226                 return;
     227             }
     228             igmp->ntoh();
     229             length-= sizeof(IGMP);
     230             if (igmp->type != IGMPMtraceResp)
     231                     return;
     232             if (length < sizeof(IGMPTrace)) {
     233                     TRACE(traceNetwork, "receive: IGMPMtraceResp from is too short\n");
     234                     return;
     235             }
     236             IGMPTrace *trace = (IGMPTrace*) (igmp + 1);
     237             trace->ntoh();
     238             length -= sizeof(IGMPTrace);
     239
     240             Mtrace* mt = pendingMtraces.head();
     241             while (mt != NULL) {
     242                 Mtrace* nextMt = pendingMtraces.next(mt);
     243                 if (mt->accept_trace(trace))
     244                     mt->receive(trace, length);
     245                 mt = nextMt;
     246             }
     247             break;
     248         }
     249
     250         default:
     251             return;
     252     }
     253     return;
     254 }
     255
     256 U16
     257 Network::cksum(const U16* addr,
         /* [<][>][^][v][top][bottom][index][help] */
     258                int len)
     259 {
     260     int nleft = len;
     261     const u_short *w = addr;
     262     u_short answer;
     263     u_short odd_byte = 0;
     264     register int sum = 0;
     265
     266     /*
     267      *  Our algorithm is simple, using a 32 bit accumulator (sum),
     268      *  we add sequential 16 bit words to it, and at the end, fold
     269      *  back all the carry bits from the top 16 bits into the lower
     270      *  16 bits.
     271      */
     272     while( nleft > 1 )  {
     273         sum += *w++;
     274         nleft -= 2;
     275     }
     276
     277     /* mop up an odd byte, if necessary */
     278     if( nleft == 1 ) {
     279         *(u_char *)(&odd_byte) = *(u_char *)w;
     280         sum += odd_byte;
     281     }
     282
     283     /*
     284      * add back carry outs from top 16 bits to low 16 bits
     285      */
     286     sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
     287     sum += (sum >> 16);                     /* add carry */
     288     answer = ~sum;                          /* truncate to 16 bits */
     289     return (answer);
     290 }
     291
     292
     293 //  Copyright (c) 1994 by the University of Southern California.
     294 //  All rights reserved.
     295 //
     296 //  Permission to use, copy, modify, and distribute this software and
     297 //  its documentation in source and binary forms for lawful
     298 //  non-commercial purposes and without fee is hereby granted, provided
     299 //  that the above copyright notice appear in all copies and that both
     300 //  the copyright notice and this permission notice appear in supporting
     301 //  documentation, and that any documentation, advertising materials,
     302 //  and other materials related to such distribution and use acknowledge
     303 //  that the software was developed by the University of Southern
     304 //  California and/or Information Sciences Institute.
     305 //  The name of the University of Southern California may not
     306 //  be used to endorse or promote products derived from this software
     307 //  without specific prior written permission.
     308 //
     309 //  THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY REPRESENTATIONS
     310 //  ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  THIS SOFTWARE IS
     311 //  PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
     312 //  INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
     313 //  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
     314 //  NON-INFRINGEMENT.
     315 //
     316 //  IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
     317 //  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
     318 //  TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
     319 //  THE USE OR PERFORMANCE OF THIS SOFTWARE.
     320 //
     321 //  Questions concerning this software should be directed to
     322 //  scan@isi.edu.
     323 //
     324
     325

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