ICMPSerializer Class Reference

#include <ICMPSerializer.h>

List of all members.


Detailed Description

Converts between ICMPMessage and binary (network byte order) ICMP header.

Public Member Functions

 ICMPSerializer ()
int serialize (ICMPMessage *pkt, unsigned char *buf, unsigned int bufsize)
void parse (unsigned char *buf, unsigned int bufsize, ICMPMessage *pkt)

Static Public Member Functions

static unsigned short checksum (unsigned char *addr, unsigned int count)

Constructor & Destructor Documentation

ICMPSerializer::ICMPSerializer (  )  [inline]

00031 {}


Member Function Documentation

int ICMPSerializer::serialize ( ICMPMessage *  pkt,
unsigned char *  buf,
unsigned int  bufsize 
)

Serializes an ICMPMessage for transmission on the wire. Returns the length of data written into buffer.

00040 {
00041     struct icmp *icmp = (struct icmp *) (buf);
00042     int packetLength;
00043 
00044     packetLength = ICMP_MINLEN;
00045 
00046     switch(pkt->getType())
00047     {
00048         case ICMP_ECHO_REQUEST:
00049         {
00050             PingPayload *pp = check_and_cast<PingPayload* >(pkt->getEncapsulatedMsg());
00051             icmp->icmp_type = ICMP_ECHO;
00052             icmp->icmp_code = 0;
00053             icmp->icmp_id   = htons(pp->getOriginatorId());
00054             icmp->icmp_seq  = htons(pp->getSeqNo());
00055             unsigned int datalen = (pp->getByteLength() - 4);
00056             for(unsigned int i=0; i < datalen; i++)
00057                 icmp->icmp_data[i] = 'a';
00058             packetLength += datalen;
00059             break;
00060         }
00061         case ICMP_ECHO_REPLY:
00062         {
00063             PingPayload *pp = check_and_cast<PingPayload* >(pkt->getEncapsulatedMsg());
00064             icmp->icmp_type = ICMP_ECHOREPLY;
00065             icmp->icmp_code = 0;
00066             icmp->icmp_id   = htons(pp->getOriginatorId());
00067             icmp->icmp_seq  = htons(pp->getSeqNo());
00068             unsigned int datalen = pp->getDataArraySize();
00069             for(unsigned int i=0; i < datalen; i++)
00070                 icmp->icmp_data[i] = pp->getData(i);
00071             packetLength += datalen;
00072             break;
00073         }
00074         case ICMP_DESTINATION_UNREACHABLE:
00075         {
00076             IPDatagram *ip = check_and_cast<IPDatagram* >(pkt->getEncapsulatedMsg());
00077             icmp->icmp_type = ICMP_UNREACH;
00078             icmp->icmp_code = pkt->getCode();
00079             packetLength += IPSerializer().serialize(ip, (unsigned char *)icmp->icmp_data, bufsize - ICMP_MINLEN);
00080             break;
00081         }
00082         case ICMP_TIME_EXCEEDED:
00083         {
00084             IPDatagram *ip = check_and_cast<IPDatagram* >(pkt->getEncapsulatedMsg());
00085             icmp->icmp_type = ICMP_TIMXCEED;
00086             icmp->icmp_code = ICMP_TIMXCEED_INTRANS;
00087             packetLength += IPSerializer().serialize(ip, (unsigned char *)icmp->icmp_data, bufsize - ICMP_MINLEN);
00088             break;
00089         }
00090         default:
00091         {
00092             packetLength = 0;
00093             EV << "Can not serialize ICMP packet: type " << pkt->getType() << " not supported.";
00094             break;
00095         }
00096     }
00097     icmp->icmp_cksum = checksum(buf, packetLength);
00098     return packetLength;
00099 }

void ICMPSerializer::parse ( unsigned char *  buf,
unsigned int  bufsize,
ICMPMessage *  pkt 
)

Puts a packet sniffed from the wire into an ICMPMessage.

00102 {
00103     struct icmp *icmp = (struct icmp*) buf;
00104 
00105     switch(icmp->icmp_type)
00106     {
00107         case ICMP_ECHO:
00108         {
00109             PingPayload *pp;
00110             char name[32];
00111 
00112             pkt->setType(ICMP_ECHO_REQUEST);
00113             pkt->setCode(0);
00114             pkt->setByteLength(4);
00115             sprintf(name,"ping%d", ntohs(icmp->icmp_seq));
00116             pp = new PingPayload(name);
00117             pp->setOriginatorId(ntohs(icmp->icmp_id));
00118             pp->setSeqNo(ntohs(icmp->icmp_seq));
00119             pp->setByteLength(bufsize - 4);
00120             pp->setDataArraySize(bufsize - ICMP_MINLEN);
00121             for(unsigned int i=0; i<bufsize - ICMP_MINLEN; i++)
00122                 pp->setData(i, icmp->icmp_data[i]);
00123             pkt->encapsulate(pp);
00124             pkt->setName(pp->getName());
00125             break;
00126         }
00127         case ICMP_ECHOREPLY:
00128         {
00129             PingPayload *pp;
00130             char name[32];
00131 
00132             pkt->setType(ICMP_ECHO_REPLY);
00133             pkt->setCode(0);
00134             pkt->setByteLength(4);
00135             sprintf(name,"ping%d-reply", ntohs(icmp->icmp_seq));
00136             pp = new PingPayload(name);
00137             pp->setOriginatorId(ntohs(icmp->icmp_id));
00138             pp->setSeqNo(ntohs(icmp->icmp_seq));
00139             pp->setByteLength(bufsize - 4);
00140             pkt->encapsulate(pp);
00141             pkt->setName(pp->getName());
00142             break;
00143         }
00144         default:
00145         {
00146             EV << "Can not create ICMP packet: type " << icmp->icmp_type << " not supported.";
00147             break;
00148         }
00149     }
00150 }

unsigned short ICMPSerializer::checksum ( unsigned char *  addr,
unsigned int  count 
) [static]

Helper: calculate checksum

00153 {
00154     long sum = 0;
00155 
00156     while (count > 1)  {
00157         sum += *((unsigned short *&)addr)++;
00158         if (sum & 0x80000000)
00159             sum = (sum & 0xFFFF) + (sum >> 16);
00160         count -= 2;
00161     }
00162 
00163     if (count)
00164         sum += *(unsigned char *)addr;
00165 
00166     while (sum >> 16)
00167         sum = (sum & 0xffff) + (sum >> 16);
00168 
00169     return ~sum;
00170 }


The documentation for this class was generated from the following files:

Generated on Fri Mar 20 18:51:19 2009 for INET Framework for OMNeT++/OMNEST by  doxygen 1.5.5