#include <ICMPSerializer.h>
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) |
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 }