00001 // 00002 // Copyright (C) 2005 Andras Varga 00003 // 00004 // This program is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public License 00006 // as published by the Free Software Foundation; either version 2 00007 // of the License, or (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU Lesser General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU Lesser General Public License 00015 // along with this program; if not, see <http://www.gnu.org/licenses/>. 00016 // 00017 00018 00019 #include <omnetpp.h> 00020 #include <stdlib.h> 00021 #include <string.h> 00022 #include "IPv6FragBuf.h" 00023 #include "ICMPv6.h" 00024 #include "ICMPv6Message_m.h" // for TIME_EXCEEDED 00025 #include "IPv6Datagram.h" 00026 #include "IPv6ExtensionHeaders_m.h" 00027 00028 00029 IPv6FragBuf::IPv6FragBuf() 00030 { 00031 icmpModule = NULL; 00032 } 00033 00034 IPv6FragBuf::~IPv6FragBuf() 00035 { 00036 } 00037 00038 void IPv6FragBuf::init(ICMPv6 *icmp) 00039 { 00040 icmpModule = icmp; 00041 } 00042 00043 IPv6Datagram *IPv6FragBuf::addFragment(IPv6Datagram *datagram, IPv6FragmentHeader *fh, simtime_t now) 00044 { 00045 // find datagram buffer 00046 Key key; 00047 key.id = fh->getIdentification(); 00048 key.src = datagram->getSrcAddress(); 00049 key.dest = datagram->getDestAddress(); 00050 00051 Buffers::iterator i = bufs.find(key); 00052 00053 DatagramBuffer *buf = NULL; 00054 if (i==bufs.end()) 00055 { 00056 // this is the first fragment of that datagram, create reassembly buffer for it 00057 buf = &bufs[key]; 00058 buf->datagram = NULL; 00059 } 00060 else 00061 { 00062 // use existing buffer 00063 buf = &(i->second); 00064 } 00065 00066 // add fragment into reassembly buffer 00067 // FIXME next lines aren't correct: check 4.5 of RFC 2460 regarding Unfragmentable part, Fragmentable part, etc 00068 int bytes = datagram->getByteLength() - datagram->calculateHeaderByteLength(); 00069 bool isComplete = buf->buf.addFragment(fh->getFragmentOffset(), 00070 fh->getFragmentOffset() + bytes, 00071 !fh->getMoreFragments()); 00072 00073 // store datagram. Only one fragment carries the actual modelled 00074 // content (getEncapsulatedMsg()), other (empty) ones are only 00075 // preserved so that we can send them in ICMP if reassembly times out. 00076 if (datagram->getEncapsulatedMsg()) 00077 { 00078 delete buf->datagram; 00079 buf->datagram = datagram; 00080 } 00081 else 00082 { 00083 delete datagram; 00084 } 00085 00086 // do we have the complete datagram? 00087 if (isComplete) 00088 { 00089 // datagram complete: deallocate buffer and return complete datagram 00090 IPv6Datagram *ret = buf->datagram; 00091 ret->setByteLength(ret->calculateHeaderByteLength()+buf->buf.getTotalLength()); // FIXME cf with 4.5 of RFC 2460 00092 //TODO: remove extension header IPv6FragmentHeader; maybe not here but when datagram gets inserted into the reassembly buffer --Andras 00093 bufs.erase(i); 00094 return ret; 00095 } 00096 else 00097 { 00098 // there are still missing fragments 00099 buf->lastupdate = now; 00100 return NULL; 00101 } 00102 } 00103 00104 void IPv6FragBuf::purgeStaleFragments(simtime_t lastupdate) 00105 { 00106 // this method shouldn't be called too often because iteration on 00107 // an std::map is *very* slow... 00108 00109 ASSERT(icmpModule); 00110 00111 for (Buffers::iterator i=bufs.begin(); i!=bufs.end(); ) 00112 { 00113 // if too old, remove it 00114 DatagramBuffer& buf = i->second; 00115 if (buf.lastupdate < lastupdate) 00116 { 00117 // send ICMP error 00118 EV << "datagram fragment timed out in reassembly buffer, sending ICMP_TIME_EXCEEDED\n"; 00119 icmpModule->sendErrorMessage(buf.datagram, ICMPv6_TIME_EXCEEDED, 0); 00120 00121 // delete 00122 Buffers::iterator oldi = i++; 00123 bufs.erase(oldi); 00124 } 00125 else 00126 { 00127 ++i; 00128 } 00129 } 00130 } 00131