UDP.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2000 Institut fuer Telematik, Universitaet Karlsruhe
00003 // Copyright (C) 2004,2005 Andras Varga
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public License
00016 // along with this program; if not, see <http://www.gnu.org/licenses/>.
00017 //
00018 
00019 
00020 //
00021 // Author: Jochen Reber
00022 // Rewrite: Andras Varga 2004,2005
00023 //
00024 
00025 #include <omnetpp.h>
00026 #include <string.h>
00027 #include "UDPPacket.h"
00028 #include "UDP.h"
00029 #include "IPControlInfo.h"
00030 #include "IPv6ControlInfo.h"
00031 #include "ICMPAccess.h"
00032 #include "ICMPv6Access.h"
00033 
00034 // the following is only for ICMP error processing
00035 #include "ICMPMessage_m.h"
00036 #include "ICMPv6Message_m.h"
00037 #include "IPDatagram_m.h"
00038 #include "IPv6Datagram_m.h"
00039 
00040 
00041 #define EPHEMERAL_PORTRANGE_START 1024
00042 #define EPHEMERAL_PORTRANGE_END   5000
00043 
00044 
00045 Define_Module( UDP );
00046 
00047 
00048 static std::ostream & operator<<(std::ostream & os, const UDP::SockDesc& sd)
00049 {
00050     os << "sockId=" << sd.sockId;
00051     os << " appGateIndex=" << sd.appGateIndex;
00052     os << " userId=" << sd.userId;
00053     os << " localPort=" << sd.localPort;
00054     if (sd.remotePort!=0)
00055         os << " remotePort=" << sd.remotePort;
00056     if (!sd.localAddr.isUnspecified())
00057         os << " localAddr=" << sd.localAddr;
00058     if (!sd.remoteAddr.isUnspecified())
00059         os << " remoteAddr=" << sd.remoteAddr;
00060     if (sd.interfaceId!=-1)
00061         os << " interfaceId=" << sd.interfaceId;
00062 
00063     return os;
00064 }
00065 
00066 static std::ostream & operator<<(std::ostream & os, const UDP::SockDescList& list)
00067 {
00068     for (UDP::SockDescList::const_iterator i=list.begin(); i!=list.end(); ++i)
00069         os << "sockId=" << (*i)->sockId << " ";
00070     return os;
00071 }
00072 
00073 //--------
00074 
00075 UDP::~UDP()
00076 {
00077     for (SocketsByIdMap::iterator i=socketsByIdMap.begin(); i!=socketsByIdMap.end(); ++i)
00078         delete i->second;
00079 }
00080 
00081 void UDP::initialize()
00082 {
00083     WATCH_PTRMAP(socketsByIdMap);
00084     WATCH_MAP(socketsByPortMap);
00085 
00086     lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00087     icmp = NULL;
00088     icmpv6 = NULL;
00089 
00090     numSent = 0;
00091     numPassedUp = 0;
00092     numDroppedWrongPort = 0;
00093     numDroppedBadChecksum = 0;
00094     WATCH(numSent);
00095     WATCH(numPassedUp);
00096     WATCH(numDroppedWrongPort);
00097     WATCH(numDroppedBadChecksum);
00098 }
00099 
00100 void UDP::bind(int gateIndex, UDPControlInfo *ctrl)
00101 {
00102     // XXX checks could be added, of when the bind should be allowed to proceed
00103 
00104     // create and fill in SockDesc
00105     SockDesc *sd = new SockDesc();
00106     sd->sockId = ctrl->getSockId();
00107     sd->userId = ctrl->getUserId();
00108     sd->appGateIndex = gateIndex;
00109     sd->localAddr = ctrl->getSrcAddr();
00110     sd->remoteAddr = ctrl->getDestAddr();
00111     sd->localPort = ctrl->getSrcPort();
00112     sd->remotePort = ctrl->getDestPort();
00113     sd->interfaceId = ctrl->getInterfaceId();
00114 
00115     if (sd->sockId==-1)
00116         error("sockId in BIND message not filled in");
00117     if (sd->localPort==0)
00118         sd->localPort = getEphemeralPort();
00119 
00120     sd->onlyLocalPortIsSet = sd->localAddr.isUnspecified() &&
00121                              sd->remoteAddr.isUnspecified() &&
00122                              sd->remotePort==0 &&
00123                              sd->interfaceId==-1;
00124 
00125     EV << "Binding socket: " << *sd << "\n";
00126 
00127     // add to socketsByIdMap
00128     ASSERT(socketsByIdMap.find(sd->sockId)==socketsByIdMap.end());
00129     socketsByIdMap[sd->sockId] = sd;
00130 
00131     // add to socketsByPortMap
00132     SockDescList& list = socketsByPortMap[sd->localPort]; // create if doesn't exist
00133     list.push_back(sd);
00134 }
00135 
00136 void UDP::connect(int sockId, IPvXAddress addr, int port)
00137 {
00138     SocketsByIdMap::iterator it = socketsByIdMap.find(sockId);
00139     if (it==socketsByIdMap.end())
00140         error("socket id=%d doesn't exist (already closed?)", sockId);
00141     if (addr.isUnspecified())
00142         opp_error("connect: unspecified remote address");
00143     if (port<=0 || port>65535)
00144         opp_error("connect: invalid remote port number %d", port);
00145 
00146     SockDesc *sd = it->second;
00147     sd->remoteAddr = addr;
00148     sd->remotePort = port;
00149 
00150     sd->onlyLocalPortIsSet = false;
00151 
00152     EV << "Connecting socket: " << *sd << "\n";
00153 }
00154 
00155 void UDP::unbind(int sockId)
00156 {
00157     // remove from socketsByIdMap
00158     SocketsByIdMap::iterator it = socketsByIdMap.find(sockId);
00159     if (it==socketsByIdMap.end())
00160         error("socket id=%d doesn't exist (already closed?)", sockId);
00161     SockDesc *sd = it->second;
00162     socketsByIdMap.erase(it);
00163 
00164     EV << "Unbinding socket: " << *sd << "\n";
00165 
00166     // remove from socketsByPortMap
00167     SockDescList& list = socketsByPortMap[sd->localPort];
00168     for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it)
00169         if (*it == sd)
00170             {list.erase(it); break;}
00171     if (list.empty())
00172         socketsByPortMap.erase(sd->localPort);
00173     delete sd;
00174 }
00175 
00176 ushort UDP::getEphemeralPort()
00177 {
00178     // start at the last allocated port number + 1, and search for an unused one
00179     ushort searchUntil = lastEphemeralPort++;
00180     if (lastEphemeralPort == EPHEMERAL_PORTRANGE_END) // wrap
00181         lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00182 
00183     while (socketsByPortMap.find(lastEphemeralPort)!=socketsByPortMap.end())
00184     {
00185         if (lastEphemeralPort == searchUntil) // got back to starting point?
00186             error("Ephemeral port range %d..%d exhausted, all ports occupied", EPHEMERAL_PORTRANGE_START, EPHEMERAL_PORTRANGE_END);
00187         lastEphemeralPort++;
00188         if (lastEphemeralPort == EPHEMERAL_PORTRANGE_END) // wrap
00189             lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00190     }
00191 
00192     // found a free one, return it
00193     return lastEphemeralPort;
00194 }
00195 
00196 void UDP::handleMessage(cMessage *msg)
00197 {
00198     // received from IP layer
00199     if (msg->arrivedOn("ipIn") || msg->arrivedOn("ipv6In"))
00200     {
00201         if (dynamic_cast<ICMPMessage *>(msg) || dynamic_cast<ICMPv6Message *>(msg))
00202             processICMPError(PK(msg));
00203         else
00204             processUDPPacket(check_and_cast<UDPPacket *>(msg));
00205     }
00206     else // received from application layer
00207     {
00208         if (msg->getKind()==UDP_C_DATA)
00209             processMsgFromApp(PK(msg));
00210         else
00211             processCommandFromApp(msg);
00212     }
00213 
00214     if (ev.isGUI())
00215         updateDisplayString();
00216 }
00217 
00218 void UDP::updateDisplayString()
00219 {
00220     char buf[80];
00221     sprintf(buf, "passed up: %d pks\nsent: %d pks", numPassedUp, numSent);
00222     if (numDroppedWrongPort>0)
00223     {
00224         sprintf(buf+strlen(buf), "\ndropped (no app): %d pks", numDroppedWrongPort);
00225         getDisplayString().setTagArg("i",1,"red");
00226     }
00227     getDisplayString().setTagArg("t",0,buf);
00228 }
00229 
00230 bool UDP::matchesSocket(SockDesc *sd, UDPPacket *udp, IPControlInfo *ipCtrl)
00231 {
00232     // IPv4 version
00233     if (sd->remotePort!=0 && sd->remotePort!=udp->getSourcePort())
00234         return false;
00235     if (!sd->localAddr.isUnspecified() && sd->localAddr.get4()!=ipCtrl->getDestAddr())
00236         return false;
00237     if (!sd->remoteAddr.isUnspecified() && sd->remoteAddr.get4()!=ipCtrl->getSrcAddr())
00238         return false;
00239     if (sd->interfaceId!=-1 && sd->interfaceId!=ipCtrl->getInterfaceId())
00240         return false;
00241     return true;
00242 }
00243 
00244 bool UDP::matchesSocket(SockDesc *sd, UDPPacket *udp, IPv6ControlInfo *ipCtrl)
00245 {
00246     // IPv6 version
00247     if (sd->remotePort!=0 && sd->remotePort!=udp->getSourcePort())
00248         return false;
00249     if (!sd->localAddr.isUnspecified() && sd->localAddr.get6()!=ipCtrl->getDestAddr())
00250         return false;
00251     if (!sd->remoteAddr.isUnspecified() && sd->remoteAddr.get6()!=ipCtrl->getSrcAddr())
00252         return false;
00253     if (sd->interfaceId!=-1 && sd->interfaceId!=ipCtrl->getInterfaceId())
00254         return false;
00255     return true;
00256 }
00257 
00258 bool UDP::matchesSocket(SockDesc *sd, const IPvXAddress& localAddr, const IPvXAddress& remoteAddr, ushort remotePort)
00259 {
00260     return (sd->remotePort==0 || sd->remotePort!=remotePort) &&
00261            (sd->localAddr.isUnspecified() || sd->localAddr==localAddr) &&
00262            (sd->remoteAddr.isUnspecified() || sd->remoteAddr==remoteAddr);
00263 }
00264 
00265 void UDP::sendUp(cPacket *payload, UDPPacket *udpHeader, IPControlInfo *ipCtrl, SockDesc *sd)
00266 {
00267     // send payload with UDPControlInfo up to the application -- IPv4 version
00268     UDPControlInfo *udpCtrl = new UDPControlInfo();
00269     udpCtrl->setSockId(sd->sockId);
00270     udpCtrl->setUserId(sd->userId);
00271     udpCtrl->setSrcAddr(ipCtrl->getSrcAddr());
00272     udpCtrl->setDestAddr(ipCtrl->getDestAddr());
00273     udpCtrl->setSrcPort(udpHeader->getSourcePort());
00274     udpCtrl->setDestPort(udpHeader->getDestinationPort());
00275     udpCtrl->setInterfaceId(ipCtrl->getInterfaceId());
00276     payload->setControlInfo(udpCtrl);
00277 
00278     send(payload, "appOut", sd->appGateIndex);
00279     numPassedUp++;
00280 }
00281 
00282 void UDP::sendUp(cPacket *payload, UDPPacket *udpHeader, IPv6ControlInfo *ipCtrl, SockDesc *sd)
00283 {
00284     // send payload with UDPControlInfo up to the application -- IPv6 version
00285     UDPControlInfo *udpCtrl = new UDPControlInfo();
00286     udpCtrl->setSockId(sd->sockId);
00287     udpCtrl->setUserId(sd->userId);
00288     udpCtrl->setSrcAddr(ipCtrl->getSrcAddr());
00289     udpCtrl->setDestAddr(ipCtrl->getDestAddr());
00290     udpCtrl->setSrcPort(udpHeader->getSourcePort());
00291     udpCtrl->setDestPort(udpHeader->getDestinationPort());
00292     udpCtrl->setInterfaceId(ipCtrl->getInterfaceId());
00293     payload->setControlInfo(udpCtrl);
00294 
00295     send(payload, "appOut", sd->appGateIndex);
00296     numPassedUp++;
00297 }
00298 
00299 void UDP::processUndeliverablePacket(UDPPacket *udpPacket, cPolymorphic *ctrl)
00300 {
00301     numDroppedWrongPort++;
00302 
00303     // send back ICMP PORT_UNREACHABLE
00304     if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL)
00305     {
00306         if (!icmp)
00307             icmp = ICMPAccess().get();
00308         IPControlInfo *ctrl4 = (IPControlInfo *)ctrl;
00309         if (!ctrl4->getDestAddr().isMulticast())
00310             icmp->sendErrorMessage(udpPacket, ctrl4, ICMP_DESTINATION_UNREACHABLE, ICMP_DU_PORT_UNREACHABLE);
00311     }
00312     else if (dynamic_cast<IPv6ControlInfo *>(udpPacket->getControlInfo())!=NULL)
00313     {
00314         if (!icmpv6)
00315             icmpv6 = ICMPv6Access().get();
00316         IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl;
00317         if (!ctrl6->getDestAddr().isMulticast())
00318             icmpv6->sendErrorMessage(udpPacket, ctrl6, ICMPv6_DESTINATION_UNREACHABLE, PORT_UNREACHABLE);
00319     }
00320     else
00321     {
00322         error("(%s)%s arrived from lower layer without control info", udpPacket->getClassName(), udpPacket->getName());
00323     }
00324 }
00325 
00326 void UDP::processICMPError(cPacket *msg)
00327 {
00328     // extract details from the error message, then try to notify socket that sent bogus packet
00329     int type, code;
00330     IPvXAddress localAddr, remoteAddr;
00331     ushort localPort, remotePort;
00332 
00333     if (dynamic_cast<ICMPMessage *>(msg))
00334     {
00335         ICMPMessage *icmpMsg = (ICMPMessage *)msg;
00336         type = icmpMsg->getType();
00337         code = icmpMsg->getCode();
00338         // Note: we must NOT use decapsulate() because payload in ICMP is conceptually truncated
00339         IPDatagram *datagram = check_and_cast<IPDatagram *>(icmpMsg->getEncapsulatedMsg());
00340         UDPPacket *packet = check_and_cast<UDPPacket *>(datagram->getEncapsulatedMsg());
00341         localAddr = datagram->getSrcAddress();
00342         remoteAddr = datagram->getDestAddress();
00343         localPort = packet->getSourcePort();
00344         remotePort = packet->getDestinationPort();
00345         delete icmpMsg;
00346     }
00347     else if (dynamic_cast<ICMPv6Message *>(msg))
00348     {
00349         ICMPv6Message *icmpMsg = (ICMPv6Message *)msg;
00350         type = icmpMsg->getType();
00351         code = -1; // FIXME this is dependent on getType()...
00352         // Note: we must NOT use decapsulate() because payload in ICMP is conceptually truncated
00353         IPv6Datagram *datagram = check_and_cast<IPv6Datagram *>(icmpMsg->getEncapsulatedMsg());
00354         UDPPacket *packet = check_and_cast<UDPPacket *>(datagram->getEncapsulatedMsg());
00355         localAddr = datagram->getSrcAddress();
00356         remoteAddr = datagram->getDestAddress();
00357         localPort = packet->getSourcePort();
00358         remotePort = packet->getDestinationPort();
00359         delete icmpMsg;
00360     }
00361     EV << "ICMP error received: type=" << type << " code=" << code
00362        << " about packet " << localAddr << ":" << localPort << " > "
00363        << remoteAddr << ":" << remotePort << "\n";
00364 
00365     // identify socket and report error to it
00366     SocketsByPortMap::iterator it = socketsByPortMap.find(localPort);
00367     if (it==socketsByPortMap.end())
00368     {
00369         EV << "No socket on that local port, ignoring ICMP error\n";
00370         return;
00371     }
00372     SockDescList& list = it->second;
00373     SockDesc *srcSocket = NULL;
00374     for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it)
00375     {
00376         SockDesc *sd = *it;
00377         if (sd->onlyLocalPortIsSet || matchesSocket(sd, localAddr, remoteAddr, remotePort))
00378         {
00379             srcSocket = sd; // FIXME what to do if there's more than one matching socket ???
00380         }
00381     }
00382     if (!srcSocket)
00383     {
00384         EV << "No matching socket, ignoring ICMP error\n";
00385         return;
00386     }
00387 
00388     // send UDP_I_ERROR to socket
00389     EV << "Source socket is sockId=" << srcSocket->sockId << ", notifying.\n";
00390     sendUpErrorNotification(srcSocket, UDP_I_ERROR, localAddr, remoteAddr, remotePort);
00391 }
00392 
00393 void UDP::sendUpErrorNotification(SockDesc *sd, int msgkind, const IPvXAddress& localAddr, const IPvXAddress& remoteAddr, ushort remotePort)
00394 {
00395     cPacket *notifyMsg = new cPacket("ERROR", msgkind);
00396     UDPControlInfo *udpCtrl = new UDPControlInfo();
00397     udpCtrl->setSockId(sd->sockId);
00398     udpCtrl->setUserId(sd->userId);
00399     udpCtrl->setSrcAddr(localAddr);
00400     udpCtrl->setDestAddr(remoteAddr);
00401     udpCtrl->setSrcPort(sd->localPort);
00402     udpCtrl->setDestPort(remotePort);
00403     notifyMsg->setControlInfo(udpCtrl);
00404 
00405     send(notifyMsg, "appOut", sd->appGateIndex);
00406 }
00407 
00408 void UDP::processUDPPacket(UDPPacket *udpPacket)
00409 {
00410     // simulate checksum: discard packet if it has bit error
00411     EV << "Packet " << udpPacket->getName() << " received from network, dest port " << udpPacket->getDestinationPort() << "\n";
00412     if (udpPacket->hasBitError())
00413     {
00414         EV << "Packet has bit error, discarding\n";
00415         delete udpPacket;
00416         numDroppedBadChecksum++;
00417         return;
00418     }
00419 
00420     int destPort = udpPacket->getDestinationPort();
00421     cPolymorphic *ctrl = udpPacket->removeControlInfo();
00422 
00423     // send back ICMP error if no socket is bound to that port
00424     SocketsByPortMap::iterator it = socketsByPortMap.find(destPort);
00425     if (it==socketsByPortMap.end())
00426     {
00427         EV << "No socket registered on port " << destPort << "\n";
00428         processUndeliverablePacket(udpPacket, ctrl);
00429         return;
00430     }
00431     SockDescList& list = it->second;
00432 
00433     int matches = 0;
00434 
00435     // deliver a copy of the packet to each matching socket
00436     cPacket *payload = udpPacket->getEncapsulatedMsg();
00437     if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL)
00438     {
00439         IPControlInfo *ctrl4 = (IPControlInfo *)ctrl;
00440         for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it)
00441         {
00442             SockDesc *sd = *it;
00443             if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl4))
00444             {
00445                 EV << "Socket sockId=" << sd->sockId << " matches, sending up a copy.\n";
00446                 sendUp((cPacket*)payload->dup(), udpPacket, ctrl4, sd);
00447                 matches++;
00448             }
00449         }
00450     }
00451     else if (dynamic_cast<IPv6ControlInfo *>(ctrl)!=NULL)
00452     {
00453         IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl;
00454         for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it)
00455         {
00456             SockDesc *sd = *it;
00457             if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl6))
00458             {
00459                 EV << "Socket sockId=" << sd->sockId << " matches, sending up a copy.\n";
00460                 sendUp((cPacket*)payload->dup(), udpPacket, ctrl6, sd);
00461                 matches++;
00462             }
00463         }
00464     }
00465     else
00466     {
00467         error("(%s)%s arrived from lower layer without control info", udpPacket->getClassName(), udpPacket->getName());
00468     }
00469 
00470     // send back ICMP error if there is no matching socket
00471     if (matches==0)
00472     {
00473         EV << "None of the sockets on port " << destPort << " matches the packet\n";
00474         processUndeliverablePacket(udpPacket, ctrl);
00475         return;
00476     }
00477 
00478     delete udpPacket;
00479     delete ctrl;
00480 }
00481 
00482 
00483 void UDP::processMsgFromApp(cPacket *appData)
00484 {
00485     UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(appData->removeControlInfo());
00486 
00487     UDPPacket *udpPacket = createUDPPacket(appData->getName());
00488     udpPacket->setByteLength(UDP_HEADER_BYTES);
00489     udpPacket->encapsulate(appData);
00490 
00491     // set source and destination port
00492     udpPacket->setSourcePort(udpCtrl->getSrcPort());
00493     udpPacket->setDestinationPort(udpCtrl->getDestPort());
00494 
00495     if (!udpCtrl->getDestAddr().isIPv6())
00496     {
00497         // send to IPv4
00498         EV << "Sending app packet " << appData->getName() << " over IPv4.\n";
00499         IPControlInfo *ipControlInfo = new IPControlInfo();
00500         ipControlInfo->setProtocol(IP_PROT_UDP);
00501         ipControlInfo->setSrcAddr(udpCtrl->getSrcAddr().get4());
00502         ipControlInfo->setDestAddr(udpCtrl->getDestAddr().get4());
00503         ipControlInfo->setInterfaceId(udpCtrl->getInterfaceId());
00504         udpPacket->setControlInfo(ipControlInfo);
00505         delete udpCtrl;
00506 
00507         send(udpPacket,"ipOut");
00508     }
00509     else
00510     {
00511         // send to IPv6
00512         EV << "Sending app packet " << appData->getName() << " over IPv6.\n";
00513         IPv6ControlInfo *ipControlInfo = new IPv6ControlInfo();
00514         ipControlInfo->setProtocol(IP_PROT_UDP);
00515         ipControlInfo->setSrcAddr(udpCtrl->getSrcAddr().get6());
00516         ipControlInfo->setDestAddr(udpCtrl->getDestAddr().get6());
00517         // ipControlInfo->setInterfaceId(udpCtrl->InterfaceId()); FIXME extend IPv6 with this!!!
00518         udpPacket->setControlInfo(ipControlInfo);
00519         delete udpCtrl;
00520 
00521         send(udpPacket,"ipv6Out");
00522     }
00523     numSent++;
00524 }
00525 
00526 UDPPacket *UDP::createUDPPacket(const char *name)
00527 {
00528     return new UDPPacket(name);
00529 }
00530 
00531 void UDP::processCommandFromApp(cMessage *msg)
00532 {
00533     UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(msg->removeControlInfo());
00534     switch (msg->getKind())
00535     {
00536         case UDP_C_BIND:
00537             bind(msg->getArrivalGate()->getIndex(), udpCtrl);
00538             break;
00539         case UDP_C_CONNECT:
00540             connect(udpCtrl->getSockId(), udpCtrl->getDestAddr(), udpCtrl->getDestPort());
00541             break;
00542         case UDP_C_UNBIND:
00543             unbind(udpCtrl->getSockId());
00544             break;
00545         default:
00546             error("unknown command code (message kind) %d received from app", msg->getKind());
00547     }
00548 
00549     delete udpCtrl;
00550     delete msg;
00551 }
00552 
00553