|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright (C) 2005 Christian Dankbar, Irene Ruengeler, Michael Tuexen, Andras Varga 00003 // 00004 // This program is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU 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 General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with this program; if not, see <http://www.gnu.org/licenses/>. 00016 // 00017 00018 #include <platdep/sockets.h> 00019 #include "headers/defs.h" 00020 namespace INETFw // load headers into a namespace, to avoid conflicts with platform definitions of the same stuff 00021 { 00022 #include "headers/bsdint.h" 00023 #include "headers/in.h" 00024 #include "headers/in_systm.h" 00025 #include "headers/ip.h" 00026 #include "headers/ip_icmp.h" 00027 }; 00028 #include "IPSerializer.h" 00029 #include "ICMPSerializer.h" 00030 #include "PingPayload_m.h" 00031 #include "TCPIPchecksum.h" 00032 00033 #if !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32) && !defined(__CYGWIN__) && !defined(_WIN64) 00034 #include <netinet/in.h> // htonl, ntohl, ... 00035 #endif 00036 00037 00038 using namespace INETFw; 00039 00040 00041 int ICMPSerializer::serialize(const ICMPMessage *pkt, unsigned char *buf, unsigned int bufsize) 00042 { 00043 struct icmp *icmp = (struct icmp *) (buf); 00044 int packetLength; 00045 00046 packetLength = ICMP_MINLEN; 00047 00048 switch(pkt->getType()) 00049 { 00050 case ICMP_ECHO_REQUEST: 00051 { 00052 PingPayload *pp = check_and_cast<PingPayload* >(pkt->getEncapsulatedPacket()); 00053 icmp->icmp_type = ICMP_ECHO; 00054 icmp->icmp_code = 0; 00055 icmp->icmp_id = htons(pp->getOriginatorId()); 00056 icmp->icmp_seq = htons(pp->getSeqNo()); 00057 unsigned int datalen = (pp->getByteLength() - 4); 00058 for (unsigned int i=0; i < datalen; i++) 00059 if (i < pp->getDataArraySize()) { 00060 icmp->icmp_data[i] = pp->getData(i); 00061 } else { 00062 icmp->icmp_data[i] = 'a'; 00063 } 00064 packetLength += datalen; 00065 break; 00066 } 00067 case ICMP_ECHO_REPLY: 00068 { 00069 PingPayload *pp = check_and_cast<PingPayload* >(pkt->getEncapsulatedPacket()); 00070 icmp->icmp_type = ICMP_ECHOREPLY; 00071 icmp->icmp_code = 0; 00072 icmp->icmp_id = htons(pp->getOriginatorId()); 00073 icmp->icmp_seq = htons(pp->getSeqNo()); 00074 unsigned int datalen = pp->getDataArraySize(); 00075 for(unsigned int i=0; i < datalen; i++) 00076 icmp->icmp_data[i] = pp->getData(i); 00077 packetLength += datalen; 00078 break; 00079 } 00080 case ICMP_DESTINATION_UNREACHABLE: 00081 { 00082 IPDatagram *ip = check_and_cast<IPDatagram* >(pkt->getEncapsulatedPacket()); 00083 icmp->icmp_type = ICMP_UNREACH; 00084 icmp->icmp_code = pkt->getCode(); 00085 packetLength += IPSerializer().serialize(ip, (unsigned char *)icmp->icmp_data, bufsize - ICMP_MINLEN); 00086 break; 00087 } 00088 case ICMP_TIME_EXCEEDED: 00089 { 00090 IPDatagram *ip = check_and_cast<IPDatagram* >(pkt->getEncapsulatedPacket()); 00091 icmp->icmp_type = ICMP_TIMXCEED; 00092 icmp->icmp_code = ICMP_TIMXCEED_INTRANS; 00093 packetLength += IPSerializer().serialize(ip, (unsigned char *)icmp->icmp_data, bufsize - ICMP_MINLEN); 00094 break; 00095 } 00096 default: 00097 { 00098 packetLength = 0; 00099 EV << "Can not serialize ICMP packet: type " << pkt->getType() << " not supported."; 00100 break; 00101 } 00102 } 00103 icmp->icmp_cksum = TCPIPchecksum::checksum(buf, packetLength); 00104 return packetLength; 00105 } 00106 00107 void ICMPSerializer::parse(const unsigned char *buf, unsigned int bufsize, ICMPMessage *pkt) 00108 { 00109 struct icmp *icmp = (struct icmp*) buf; 00110 00111 switch(icmp->icmp_type) 00112 { 00113 case ICMP_ECHO: 00114 { 00115 PingPayload *pp; 00116 char name[32]; 00117 00118 pkt->setType(ICMP_ECHO_REQUEST); 00119 pkt->setCode(0); 00120 pkt->setByteLength(4); 00121 sprintf(name,"ping%d", ntohs(icmp->icmp_seq)); 00122 pp = new PingPayload(name); 00123 pp->setOriginatorId(ntohs(icmp->icmp_id)); 00124 pp->setSeqNo(ntohs(icmp->icmp_seq)); 00125 pp->setByteLength(bufsize - 4); 00126 pp->setDataArraySize(bufsize - ICMP_MINLEN); 00127 for(unsigned int i=0; i<bufsize - ICMP_MINLEN; i++) 00128 pp->setData(i, icmp->icmp_data[i]); 00129 pkt->encapsulate(pp); 00130 pkt->setName(pp->getName()); 00131 break; 00132 } 00133 case ICMP_ECHOREPLY: 00134 { 00135 PingPayload *pp; 00136 char name[32]; 00137 00138 pkt->setType(ICMP_ECHO_REPLY); 00139 pkt->setCode(0); 00140 pkt->setByteLength(4); 00141 sprintf(name,"ping%d-reply", ntohs(icmp->icmp_seq)); 00142 pp = new PingPayload(name); 00143 pp->setOriginatorId(ntohs(icmp->icmp_id)); 00144 pp->setSeqNo(ntohs(icmp->icmp_seq)); 00145 pp->setByteLength(bufsize - 4); 00146 pp->setDataArraySize(bufsize - ICMP_MINLEN); 00147 for (unsigned int i=0; i<bufsize - ICMP_MINLEN; i++) 00148 pp->setData(i, icmp->icmp_data[i]); 00149 pkt->encapsulate(pp); 00150 pkt->setName(pp->getName()); 00151 break; 00152 } 00153 default: 00154 { 00155 EV << "Can not create ICMP packet: type " << icmp->icmp_type << " not supported."; 00156 break; 00157 } 00158 } 00159 }