ExtInterface.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2004 Andras Varga
00003 // Copyright (C) 2005 Christian Dankbar, Irene Ruengeler, Michael Tuexen
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, see <http://www.gnu.org/licenses/>.
00017 //
00018 
00019 // This file is based on the PPP.cc of INET written by Andras Varga.
00020 
00021 #define WANT_WINSOCK2
00022 
00023 #include <platdep/sockets.h>
00024 #include <stdio.h>
00025 #include <string.h>
00026 #include <omnetpp.h>
00027 #include "InterfaceTable.h"
00028 #include "InterfaceTableAccess.h"
00029 #include "ExtInterface.h"
00030 #include "IPSerializer.h"
00031 
00032 
00033 Define_Module(ExtInterface);
00034 
00035 void ExtInterface::initialize(int stage)
00036 {
00037     // subscribe at scheduler for external messages
00038     if(stage == 0)
00039     {
00040         if(dynamic_cast<cSocketRTScheduler *>(simulation.getScheduler()) != NULL)
00041         {
00042             rtScheduler = check_and_cast<cSocketRTScheduler *>(simulation.getScheduler());
00043             //device = ev.config()->getAsString("Capture", "device", "lo0");
00044             device = par("device");
00045             //const char *filter = ev.config()->getAsString("Capture", "filter-string", "ip");
00046             const char *filter = par("filterString");
00047             rtScheduler->setInterfaceModule(this, device, filter);
00048             connected = true;
00049         }
00050         else
00051         {
00052             // this simulation run works without external interface..
00053             connected = false;
00054         }
00055     }
00056 
00057     if (stage == 3)
00058     {
00059         // update display string when addresses have been autoconfigured etc.
00060         updateDisplayString();
00061         return;
00062     }
00063 
00064     // all initialization is done in the first stage
00065     if (stage != 0)
00066         return;
00067 
00068     numSent = numRcvd = numDropped = 0;
00069     WATCH(numSent);
00070     WATCH(numRcvd);
00071     WATCH(numDropped);
00072 
00073     // register our interface entry in RoutingTable
00074     interfaceEntry = registerInterface();
00075 
00076     // if not connected, make it gray
00077     if (ev.isGUI() && !connected)
00078     {
00079         getDisplayString().setTagArg("i",1,"#707070");
00080         getDisplayString().setTagArg("i",2,"100");
00081     }
00082 }
00083 
00084 InterfaceEntry *ExtInterface::registerInterface()
00085 {
00086     InterfaceEntry *e = new InterfaceEntry();
00087 
00088     // interface name: our module name without special characters ([])
00089     char *interfaceName = new char[strlen(getFullName())+1];
00090     char *d=interfaceName;
00091     for (const char *s=getFullName(); *s; s++)
00092     if (isalnum(*s))
00093         *d++ = *s;
00094     *d = '\0';
00095     e->setName(interfaceName);
00096     delete [] interfaceName;
00097 
00098     e->setMtu(par("mtu"));
00099     e->setMulticast(true);
00100     e->setPointToPoint(true);
00101     IInterfaceTable *ift = InterfaceTableAccess().get();
00102     ift->addInterface(e, this);
00103     return e;
00104 }
00105 
00106 void ExtInterface::handleMessage(cMessage *msg)
00107 {
00108 
00109     if(dynamic_cast<ExtFrame *>(msg) != NULL)
00110     {
00111         // incoming real packet from wire (captured by pcap)
00112         uint32 packetLength;
00113         ExtFrame *rawPacket = check_and_cast<ExtFrame *>(msg);
00114 
00115         packetLength = rawPacket->getDataArraySize();
00116         for(uint32 i=0; i < packetLength; i++)
00117             buffer[i] = rawPacket->getData(i);
00118 
00119         IPDatagram *ipPacket = new IPDatagram("ip-from-wire");
00120         IPSerializer().parse(buffer, packetLength, (IPDatagram *)ipPacket);
00121         EV << "Delivering an IP packet from "
00122            << ipPacket->getSrcAddress()
00123            << " to "
00124            << ipPacket->getDestAddress()
00125            << " and length of"
00126            << ipPacket->getByteLength()
00127            << " bytes to IP layer.\n";
00128         send(ipPacket, "netwOut");
00129         numRcvd++;
00130     }
00131     else
00132     {
00133         memset(buffer, 0, 1<<16);
00134         IPDatagram *ipPacket = check_and_cast<IPDatagram *>(msg);
00135 
00136         if ((ipPacket->getTransportProtocol() != IP_PROT_ICMP) &&
00137             (ipPacket->getTransportProtocol() != IPPROTO_SCTP) &&
00138             (ipPacket->getTransportProtocol() != IPPROTO_TCP) &&
00139             (ipPacket->getTransportProtocol() != IPPROTO_UDP))
00140         {
00141             EV << "Can not send packet. Protocol " << ipPacket->getTransportProtocol() << " is not supported.\n";
00142             numDropped++;
00143             delete(msg);
00144             return;
00145         }
00146 
00147         if(connected)
00148         {
00149             struct sockaddr_in addr;
00150             addr.sin_family      = AF_INET;
00151 #if !defined(linux) && !defined(_WIN32)
00152             addr.sin_len         = sizeof(struct sockaddr_in);
00153 #endif
00154             addr.sin_port        = 0;
00155             addr.sin_addr.s_addr = htonl(ipPacket->getDestAddress().getInt());
00156             int32 packetLength = IPSerializer().serialize(ipPacket,buffer, sizeof(buffer));
00157             EV << "Delivering an IP packet from "
00158                << ipPacket->getSrcAddress()
00159                << " to "
00160                << ipPacket->getDestAddress()
00161                << " and length of "
00162                << ipPacket->getByteLength()
00163                << " bytes to link layer.\n";
00164             rtScheduler->sendBytes(buffer, packetLength, (struct sockaddr *) &addr, sizeof(struct sockaddr_in));
00165             numSent++;
00166         }
00167         else
00168         {
00169             EV << "Interface is not connected, dropping packet " << msg << endl;
00170             numDropped++;
00171         }
00172     }
00173     delete(msg);
00174     if (ev.isGUI())
00175         updateDisplayString();
00176 }
00177 
00178 void ExtInterface::displayBusy()
00179 {
00180     getDisplayString().setTagArg("i",1, "yellow");
00181     gate("physOut")->getDisplayString().setTagArg("ls",0,"yellow");
00182     gate("physOut")->getDisplayString().setTagArg("ls",1,"3");
00183 }
00184 
00185 void ExtInterface::displayIdle()
00186 {
00187     getDisplayString().setTagArg("i",1,"");
00188     gate("physOut")->getDisplayString().setTagArg("ls",0,"black");
00189     gate("physOut")->getDisplayString().setTagArg("ls",1,"1");
00190 }
00191 
00192 void ExtInterface::updateDisplayString()
00193 {
00194     char buf[80];
00195     if (ev.disable_tracing)
00196         getDisplayString().setTagArg("t",0,"");
00197     if(connected)
00198         sprintf(buf, "pcap device: %s\nrcv:%d snt:%d", device, numRcvd, numSent);
00199     else
00200         sprintf(buf, "not connected");
00201     getDisplayString().setTagArg("t", 0, buf);
00202 }
00203 
00204 void ExtInterface::finish()
00205 {
00206     std::cout << getFullPath() << ": " << numSent << " packets sent, " <<
00207             numRcvd << " packets received, " << numDropped <<" packets dropped.\n";
00208 }
00209