IPSerializer.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2005 Christian Dankbar, Irene Ruengeler, Michael Tuexen, Andras Varga
00003 // Copyright (C) 2009 Thomas Reschka
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 #include <algorithm> // std::min
00020 #include <platdep/sockets.h>
00021 #include "headers/defs.h"
00022 
00023 namespace INETFw // load headers into a namespace, to avoid conflicts with platform definitions of the same stuff
00024 {
00025 #include "headers/bsdint.h"
00026 #include "headers/in.h"
00027 #include "headers/in_systm.h"
00028 #include "headers/ip.h"
00029 };
00030 
00031 #include "IPSerializer.h"
00032 #include "ICMPSerializer.h"
00033 #include "UDPSerializer.h"
00034 #include "SCTPSerializer.h"    //I.R.
00035 #include "TCPSerializer.h"    //I.R.
00036 
00037 #if defined(_MSC_VER)
00038 #undef s_addr   /* MSVC #definition interferes with us */
00039 #endif
00040 
00041 #if !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32) && !defined(__CYGWIN__) && !defined(_WIN64)
00042 #include <netinet/in.h>  // htonl, ntohl, ...
00043 #endif
00044 
00045 #ifndef IP_PROT_SCTP    //I.R.
00046 #define IP_PROT_SCTP 132
00047 #endif
00048 
00049 // This in_addr field is defined as a macro in Windows and Solaris, which interferes with us
00050 #undef s_addr
00051 
00052 
00053 using namespace INETFw;
00054 
00055 
00056 
00057 int IPSerializer::serialize(const IPDatagram *dgram, unsigned char *buf, unsigned int bufsize)
00058 {
00059     int packetLength;
00060     struct ip *ip = (struct ip *) buf;
00061 
00062     ip->ip_hl         = IP_HEADER_BYTES >> 2;
00063     ip->ip_v          = dgram->getVersion();
00064     ip->ip_tos        = dgram->getDiffServCodePoint();
00065     ip->ip_id         = htons(dgram->getIdentification());
00066     ip->ip_off        = htons(dgram->getFragmentOffset());
00067     ip->ip_ttl        = dgram->getTimeToLive();
00068     ip->ip_p          = dgram->getTransportProtocol();
00069     ip->ip_src.s_addr = htonl(dgram->getSrcAddress().getInt());
00070     ip->ip_dst.s_addr = htonl(dgram->getDestAddress().getInt());
00071     ip->ip_sum        = 0;
00072 
00073     if (dgram->getHeaderLength() > IP_HEADER_BYTES)
00074         EV << "Serializing an IP packet with options. Dropping the options.\n";
00075 
00076     packetLength = IP_HEADER_BYTES;
00077 
00078     cMessage *encapPacket = dgram->getEncapsulatedMsg();
00079     switch (dgram->getTransportProtocol())
00080     {
00081       case IP_PROT_ICMP:
00082         packetLength += ICMPSerializer().serialize(check_and_cast<ICMPMessage *>(encapPacket),
00083                                                    buf+IP_HEADER_BYTES, bufsize-IP_HEADER_BYTES);
00084         break;
00085       case IP_PROT_UDP:
00086         packetLength += UDPSerializer().serialize(check_and_cast<UDPPacket *>(encapPacket),
00087                                                    buf+IP_HEADER_BYTES, bufsize-IP_HEADER_BYTES);
00088         break;
00089       case IP_PROT_SCTP:    //I.R.
00090         packetLength += SCTPSerializer().serialize(check_and_cast<SCTPMessage *>(encapPacket),
00091                                                    buf+IP_HEADER_BYTES, bufsize-IP_HEADER_BYTES);
00092         break;
00093       case IP_PROT_TCP:        //I.R.
00094         packetLength += TCPSerializer().serialize(check_and_cast<TCPSegment *>(encapPacket),
00095                                                    buf+IP_HEADER_BYTES, bufsize-IP_HEADER_BYTES,
00096                                                    dgram->getSrcAddress(), dgram->getDestAddress());
00097         break;
00098       default:
00099         opp_error("IPSerializer: cannot serialize protocol %d", dgram->getTransportProtocol());
00100     }
00101 
00102     ip->ip_len = htons(packetLength);
00103 
00104     return packetLength;
00105 }
00106 
00107 void IPSerializer::parse(const unsigned char *buf, unsigned int bufsize, IPDatagram *dest)
00108 {
00109     const struct ip *ip = (const struct ip *) buf;
00110     unsigned int totalLength, headerLength;
00111 
00112     dest->setVersion(ip->ip_v);
00113     dest->setHeaderLength(IP_HEADER_BYTES);
00114     dest->setSrcAddress(ntohl(ip->ip_src.s_addr));
00115     dest->setDestAddress(ntohl(ip->ip_dst.s_addr));
00116     dest->setTransportProtocol(ip->ip_p);
00117     dest->setTimeToLive(ip->ip_ttl);
00118     dest->setIdentification(ntohs(ip->ip_id));
00119     dest->setMoreFragments((ip->ip_off) & !IP_OFFMASK & IP_MF);
00120     dest->setDontFragment((ip->ip_off) & !IP_OFFMASK & IP_DF);
00121     dest->setFragmentOffset((ntohs(ip->ip_off)) & IP_OFFMASK);
00122     dest->setDiffServCodePoint(ip->ip_tos);
00123     totalLength = ntohs(ip->ip_len);
00124     headerLength = ip->ip_hl << 2;
00125 
00126     if (headerLength > (unsigned int)IP_HEADER_BYTES)
00127         EV << "Handling an captured IP packet with options. Dropping the options.\n";
00128     if (totalLength > bufsize)
00129         EV << "Can not handle IP packet of total length " << totalLength << "(captured only " << bufsize << " bytes).\n";
00130     dest->setByteLength(IP_HEADER_BYTES);
00131 
00132     cPacket *encapPacket = NULL;
00133     switch (dest->getTransportProtocol())
00134     {
00135       case IP_PROT_ICMP:
00136         encapPacket = new ICMPMessage("icmp-from-wire");
00137         ICMPSerializer().parse(buf + headerLength, std::min(totalLength, bufsize) - headerLength, (ICMPMessage *)encapPacket);
00138         break;
00139       case IP_PROT_UDP:
00140         encapPacket = new UDPPacket("udp-from-wire");
00141         UDPSerializer().parse(buf + headerLength, std::min(totalLength, bufsize) - headerLength, (UDPPacket *)encapPacket);
00142         break;
00143       case IP_PROT_SCTP:
00144         encapPacket = new SCTPMessage("sctp-from-wire");
00145         SCTPSerializer().parse(buf + headerLength, (unsigned int)(std::min(totalLength, bufsize) - headerLength), (SCTPMessage *)encapPacket);
00146         break;
00147       case IP_PROT_TCP:
00148         encapPacket = new TCPSegment("tcp-from-wire");
00149         TCPSerializer().parse(buf + headerLength, (unsigned int)(std::min(totalLength, bufsize) - headerLength), (TCPSegment *)encapPacket);
00150         break;
00151       default:
00152         opp_error("IPSerializer: cannot serialize protocol %d", dest->getTransportProtocol());
00153     }
00154 
00155     ASSERT(encapPacket);
00156     dest->encapsulate(encapPacket);
00157     dest->setName(encapPacket->getName());
00158 }