TunOutDevice Class Reference

#include <TunOutDevice.h>

List of all members.


Detailed Description

TunOutDevice is a pseudo interface that allows communcation with the real world through the cTunOutScheduler.

WARNING: This does ONLY work with the combination IPv4|UDP|OverlayMessage


Public Member Functions

 Module_Class_Members (TunOutDevice, cSimpleModule, 0)
virtual int numInitStages () const
virtual void initialize (int stage)
 Initialization of the module.
virtual void handleMessage (cMessage *msg)
 The "main loop".

Protected Member Functions

InterfaceEntry * registerInterface ()
 Register the interface in the interface table of the parent.
void transmitToTun (cMessage *msg)
 Send a message to the tun device.
void updateDisplayString ()
virtual char * encapsulate (cMessage *msg, unsigned int *length)
 Converts an IP datagram to a data block for sending it to the tun device.
virtual cMessage * decapsulate (char *buf)
 Parses data received from the tun device and converts it into a cMessage.

Protected Attributes

InterfaceEntry * interfaceEntry
unsigned int mtu
long numSent
long numSendError
long numRcvdOK
long numRcvError
cMessage * packetNotification
cTunOutScheduler::PacketBuffer packetBuffer
cTunOutSchedulerscheduler
PacketParserparser


Member Function Documentation

cMessage * TunOutDevice::decapsulate ( char *  buf  )  [protected, virtual]

Parses data received from the tun device and converts it into a cMessage.

Parameters:
buf A pointer to the data to be parsed
Returns:
The parsed message
00228 {
00229     // Message starts with IP header
00230     iphdr* ip_buf = (iphdr*) buf;
00231     udphdr* udp_buf;
00232     IPDatagram* IP = new IPDatagram;
00233     UDPPacket* UDP = new UDPPacket;
00234     cMessage* payload = 0;
00235     unsigned int payloadLen, datagramlen;
00236     unsigned int packetlen = ntohs(ip_buf->tot_len);
00237 
00238     // Parsing of IP header, sanity checks
00239     if (  packetlen > mtu ) {
00240         ev << "TunOutDevice: Dropping bogus packet, length = " << packetlen << " but mtu = " << mtu <<".\n";
00241         goto parse_error;
00242     }
00243     if ( ip_buf->version != 4 ) {
00244         ev << "TunOutDevice: Dropping Packet: Packet is not IPv4.\n";
00245         goto parse_error;
00246     }
00247     if ( ntohs(ip_buf->frag_off) & 0xBFFF ) { // mask DF bit
00248         ev << "TunOutDevice: Dropping Packet: Can't handle fragmented packets.\n";
00249         goto parse_error;
00250     }
00251     if ( ip_buf->protocol != IPPROTO_UDP ) { // FIXME: allow ICMP packets
00252         ev << "TunOutDevice: Dropping Packet: Packet is not UDP.\n";
00253         goto parse_error;
00254     }
00255     IP->setSrcAddress( IPAddress( ntohl(ip_buf->saddr) ));
00256     IP->setDestAddress( IPAddress( ntohl(ip_buf->daddr) ));
00257     IP->setTransportProtocol( ip_buf->protocol );
00258     IP->setTimeToLive( ip_buf->ttl );
00259     IP->setIdentification( ntohs(ip_buf->id) );
00260     IP->setMoreFragments( false );
00261     IP->setDontFragment( true );
00262     IP->setFragmentOffset( 0 );
00263     IP->setDiffServCodePoint( ip_buf->tos );
00264     IP->setLength( ip_buf->ihl*32 );
00265     // FIXME: check IP and UDP checksum...
00266 
00267     // Parse UDP header, sanity checks
00268     udp_buf = (udphdr*)( ((uint32_t *)ip_buf) + ip_buf->ihl );
00269     datagramlen = ntohs(udp_buf->len);
00270     if ( (datagramlen != packetlen - ip_buf->ihl*4) ) {
00271         ev << "TunOutDevice: Dropping Packet: Bogus UDP datagram length: len = " << datagramlen << " packetlen = " << packetlen << " ihl*4 " << ip_buf->ihl*4 << ".\n";
00272         goto parse_error;
00273     }
00274     UDP->setSourcePort( ntohs( udp_buf->source ));
00275     UDP->setDestinationPort( ntohs( udp_buf->dest ));
00276     UDP->setByteLength( sizeof( struct udphdr ) );
00277 
00278     // parse payload
00279     payloadLen = datagramlen - sizeof( struct udphdr );
00280     payload = parser->decapsulatePayload( ((char*) udp_buf) + sizeof( struct udphdr ), payloadLen );
00281     if (!payload) {
00282         ev << "TunOutDevice: Parsing of Payload failed, dropping packet.\n";
00283         goto parse_error;
00284     }
00285     // encapsulate messages
00286     UDP->encapsulate( payload );
00287     IP->encapsulate( UDP );
00288 
00289     delete buf;
00290     return IP;
00291 
00292     // In case the parsing of the packet failed, free allocated memory
00293 parse_error:
00294     delete buf;
00295     delete IP;
00296     delete UDP;
00297     return NULL;
00298 }

char * TunOutDevice::encapsulate ( cMessage *  msg,
unsigned int *  length 
) [protected, virtual]

Converts an IP datagram to a data block for sending it to the tun device.

Parameters:
msg A pointer to the message to be converted
length A pointer to an int that will hold the length of the converted data
Returns:
A pointer to the converted data
00146 {
00147     struct udppseudohdr {
00148         uint32_t saddr;
00149         uint32_t daddr;
00150         uint8_t zero;
00151         uint8_t protocol;
00152         uint16_t lenght;
00153     }
00154     * pseudohdr;
00155 
00156     unsigned int payloadlen;
00157     static unsigned int iplen = 20; // we don't generate IP options
00158     static unsigned int udplen = 8;
00159 
00160     IPDatagram* IP = check_and_cast<IPDatagram*>(msg);
00161     // FIXME: Check for ICMP-Messages
00162     UDPPacket* UDP = check_and_cast<UDPPacket*>(IP->decapsulate());
00163     cMessage* payloadMsg = UDP->decapsulate();
00164 
00165     // parse payload
00166     char* payload = parser->encapsulatePayload(payloadMsg, &payloadlen);
00167     if (!payload )
00168         return NULL;
00169 
00170     *length = payloadlen + iplen + udplen;
00171     if( *length > mtu ) {
00172         EV << "TunOutDevice::encapsulate: Error: Packet too big! Size = " << *length << " MTU = " << mtu << "\n";
00173         return NULL;
00174     }
00175 
00176     char* buf = new char[*length];
00177 
00178     // We use the buffer to build an ip packet.
00179     // To minimise unnecessary copying, we start with the payload
00180     // and write it to the end of the buffer
00181     memcpy( (buf + iplen + udplen), payload, payloadlen);
00182 
00183     // write udp header in front of the payload
00184     udphdr* udp_buf = (udphdr*) (buf + iplen);
00185     udp_buf->source = htons(UDP->sourcePort());
00186     udp_buf->dest = htons(UDP->destinationPort());
00187     udp_buf->len = htons(udplen + payloadlen);
00188     udp_buf->check = 0;
00189 
00190     // Write udp pseudoheader in from of udp header
00191     // this will be overwritten by ip header
00192     pseudohdr = (udppseudohdr*) (buf + iplen - sizeof(struct udppseudohdr));
00193     uint32_t saddr = htonl(IP->srcAddress().getInt());
00194     uint32_t daddr = htonl(IP->destAddress().getInt());
00195     pseudohdr->saddr = saddr;
00196     pseudohdr->daddr = daddr;
00197     pseudohdr->zero = 0;
00198     pseudohdr->protocol = IPPROTO_UDP;
00199     pseudohdr->lenght = udp_buf->len;
00200 
00201     // compute UDP checksum
00202     udp_buf->check = cksum((uint16_t*) pseudohdr, sizeof(struct udppseudohdr) + udplen + payloadlen);
00203 
00204     // write ip header to begin of buffer
00205     iphdr* ip_buf = (iphdr*) buf;
00206     ip_buf->version = 4; // IPv4
00207     ip_buf->ihl = iplen / 4;
00208     ip_buf->tos = IP->diffServCodePoint();
00209     ip_buf->tot_len = htons(*length);
00210     ip_buf->id = htons(IP->identification());
00211     ip_buf->frag_off = htons(IP_DF); // DF, no fragments
00212     ip_buf->ttl = IP->timeToLive();
00213     ip_buf->protocol = IPPROTO_UDP;
00214     ip_buf->saddr = saddr;
00215     ip_buf->daddr = daddr;
00216     ip_buf->check = 0;
00217     ip_buf->check = cksum((uint16_t*) ip_buf, iplen);
00218 
00219     delete IP;
00220     delete UDP;
00221     delete payloadMsg;
00222     delete payload;
00223 
00224     return buf;
00225 }

void TunOutDevice::handleMessage ( cMessage *  msg  )  [virtual]

The "main loop".

Every message that is received or send is handled by this method

00093 {
00094     // Packet from the real world...
00095     if (msg==packetNotification) {
00096         EV << "TunOutDevice: Message from outside. Queue length = " << packetBuffer.size() << ".\n";
00097         while( packetBuffer.size() > 0 ) {
00098             // get packet from buffer and parse it
00099             char* buf = *(packetBuffer.begin());
00100             packetBuffer.pop_front();
00101             cMessage *parsedPacket = decapsulate(buf);
00102             if (parsedPacket) {
00103                 numRcvdOK++;
00104 #ifndef _MAX_SPEED
00105 
00106                 send(parsedPacket,"netwOut");
00107 #else
00108 
00109                 send(parsedPacket, gateIndexNetwOut);
00110 #endif
00111 
00112             } else {
00113                 numRcvError++;
00114             }
00115 
00116         }
00117     } else // arrived on gate "netwIn"
00118     {
00119         // Packet from inside, send to real word
00120 #ifndef _MAX_SPEED
00121         EV << "Received " << msg << " for transmission\n"; // ib: speed hack
00122 #endif
00123 
00124         transmitToTun(msg);
00125     }
00126 
00127     if (ev.isGUI())
00128         updateDisplayString();
00129 
00130 }

void TunOutDevice::initialize ( int  stage  )  [virtual]

Initialization of the module.

Registers the device at the scheduler and searches for the appropriate payload-parser Will be called automatically at startup

00016 {
00017     error("The TunOut underlay doesn't work in this version (work in progress)!");
00018 
00019     if (stage==3) {
00020         // update display string when addresses have been autoconfigured etc.
00021         updateDisplayString();
00022         return;
00023     }
00024 
00025     // all initialization is done in the first stage
00026     if (stage!=0)
00027         return;
00028 
00029     interfaceEntry = NULL;
00030     packetNotification = new cMessage("packetNotification");
00031     mtu = par("mtu");
00032 
00033     scheduler = check_and_cast<cTunOutScheduler *>(simulation.scheduler());
00034     scheduler->setInterfaceModule(this, packetNotification, &packetBuffer, mtu);
00035 
00036     parser = check_and_cast<PacketParser*>(parentModule()->submodule("packetParser"));
00037     numSent = numRcvdOK = numRcvError = numSendError = 0;
00038     WATCH(numSent);
00039     WATCH(numRcvdOK);
00040     WATCH(numRcvError);
00041     WATCH(numSendError);
00042 
00043 #ifdef _MAX_SPEED
00044 
00045     gateIndexNetwOut = gate("netwOut")->id();
00046 #endif
00047 
00048     // register our interface entry in RoutingTable
00049     interfaceEntry = registerInterface();
00050 
00051 }

TunOutDevice::Module_Class_Members ( TunOutDevice  ,
cSimpleModule  ,
 
)

virtual int TunOutDevice::numInitStages (  )  const [inline, virtual]

00104     {
00105         return 4;
00106     }

InterfaceEntry * TunOutDevice::registerInterface (  )  [protected]

Register the interface in the interface table of the parent.

Returns:
A pointer to the Interface entry
00054 {
00055     InterfaceEntry *e = new InterfaceEntry();
00056 
00057     // interface name: our module name without special characters ([])
00058     char *interfaceName = new char[strlen(parentModule()->fullName())+1];
00059     char *d=interfaceName;
00060     for (const char *s=parentModule()->fullName(); *s; s++)
00061         if (isalnum(*s))
00062             *d++ = *s;
00063     *d = '\0';
00064 
00065     e->setName(interfaceName);
00066     delete [] interfaceName;
00067 
00068     // port: index of gate where our "netwIn" is connected (in IP)
00069     int outputPort = /*parentModule()->*/gate("netwIn")->fromGate()->index();
00070     e->setNodeOutputGateId(outputPort);
00071 
00072     // generate a link-layer address to be used as interface token for IPv6
00073     InterfaceToken token(0, simulation.getUniqueNumber(), 64);
00074     e->setInterfaceToken(token);
00075 
00076     // MTU: typical values are 576 (Internet de facto), 1500 (Ethernet-friendly),
00077     // 4000 (on some point-to-point links), 4470 (Cisco routers default, FDDI compatible)
00078     e->setMtu(mtu);
00079 
00080     // capabilities
00081     e->setMulticast(true);
00082     e->setPointToPoint(true);
00083 
00084     // add
00085     InterfaceTable *ift = InterfaceTableAccess().get();
00086     ift->addInterface(e, NULL);
00087 
00088     return e;
00089 }

void TunOutDevice::transmitToTun ( cMessage *  msg  )  [protected]

Send a message to the tun device.

Parameters:
msg A pointer to the message to be send
00133 {
00134     unsigned int length;
00135     char* buf = encapsulate(msg, &length);
00136     if( buf ) {
00137         numSent++;
00138         scheduler->sendBytes( buf, length );
00139     } else {
00140         numSendError++;
00141     }
00142     delete buf;
00143 }

void TunOutDevice::updateDisplayString (  )  [protected]

00301 {
00302     char buf[80];
00303     if (ev.disabled()) {
00304         // speed up things
00305         displayString().setTagArg("t",0,"");
00306     }
00307     sprintf(buf, "rcv:%ld snt:%ld", numRcvdOK, numSent);
00308 
00309     if (numRcvError>0)
00310         sprintf(buf+strlen(buf), "\nerrin:%ld errout:%ld", numRcvError, numSendError);
00311 
00312     displayString().setTagArg("t",0,buf);
00313 }


Member Data Documentation

InterfaceEntry* TunOutDevice::interfaceEntry [protected]

unsigned int TunOutDevice::mtu [protected]

long TunOutDevice::numRcvdOK [protected]

long TunOutDevice::numRcvError [protected]

long TunOutDevice::numSendError [protected]

long TunOutDevice::numSent [protected]

cTunOutScheduler::PacketBuffer TunOutDevice::packetBuffer [protected]

cMessage* TunOutDevice::packetNotification [protected]

PacketParser* TunOutDevice::parser [protected]

cTunOutScheduler* TunOutDevice::scheduler [protected]


The documentation for this class was generated from the following files:
Generated on Fri Dec 15 17:50:31 2006 for ITM OverSim by  doxygen 1.4.7