#include <TCPDump.h>
List of all members.
Public Member Functions |
| TCPDumper (std::ostream &o) |
| ~TCPDumper () |
void | setVerbosity (const int32 verbosityLevel) |
void | ipDump (const char *label, IPDatagram *dgram, const char *comment=NULL) |
void | sctpDump (const char *label, SCTPMessage *sctpmsg, const std::string &srcAddr, const std::string &destAddr, const char *comment=NULL) |
void | dump (const char *label, const char *msg) |
void | tcpDump (bool l2r, const char *label, IPDatagram *dgram, const char *comment=NULL) |
void | tcpDump (bool l2r, const char *label, TCPSegment *tcpseg, const std::string &srcAddr, const std::string &destAddr, const char *comment=NULL) |
void | dumpIPv6 (bool l2r, const char *label, IPv6Datagram_Base *dgram, const char *comment=NULL) |
void | udpDump (bool l2r, const char *label, IPDatagram *dgram, const char *comment) |
const char * | intToChunk (int32 type) |
Public Attributes |
FILE * | dumpfile |
Protected Attributes |
int32 | seq |
std::ostream * | outp |
Private Attributes |
int | verbosity |
Detailed Description
Dumps SCTP packets in tcpdump format.
Constructor & Destructor Documentation
TCPDumper::TCPDumper |
( |
std::ostream & |
o | ) |
|
TCPDumper::~TCPDumper |
( |
| ) |
|
Member Function Documentation
void TCPDumper::dump |
( |
const char * |
label, |
|
|
const char * |
msg |
|
) |
| |
Referenced by TCPDump::finish().
{
std::ostream& out = *outp;
char buf[30];
sprintf(buf,"[%.3f%s] ", simulation.getSimTime().dbl(), label);
out << buf;
out << msg << "\n";
}
void TCPDumper::dumpIPv6 |
( |
bool |
l2r, |
|
|
const char * |
label, |
|
|
IPv6Datagram_Base * |
dgram, |
|
|
const char * |
comment = NULL |
|
) |
| |
Referenced by TCPDump::handleMessage().
{
cMessage *encapmsg = dgram->getEncapsulatedPacket();
if (dynamic_cast<TCPSegment *>(encapmsg))
{
tcpDump(l2r, label, (TCPSegment *)encapmsg, dgram->getSrcAddress().str(), dgram->getDestAddress().str(), comment);
}
else
{
std::ostream& out = *outp;
char buf[30];
sprintf(buf,"[%.3f%s] ", SIMTIME_DBL(simTime()), label);
out << buf;
out << "? " << encapmsg->getClassName() << " \"" << encapmsg->getName() << "\"\n";
}
}
const char * TCPDumper::intToChunk |
( |
int32 |
type | ) |
|
{
switch (type)
{
case 0: return "DATA";
case 1: return "INIT";
case 2: return "INIT_ACK";
case 3: return "SACK";
case 4: return "HEARTBEAT";
case 5: return "HEARTBEAT_ACK";
case 6: return "ABORT";
case 7: return "SHUTDOWN";
case 8: return "SHUTDOWN_ACK";
case 9: return "ERRORTYPE";
case 10: return "COOKIE_ECHO";
case 11: return "COOKIE_ACK";
case 14: return "SHUTDOWN_COMPLETE";
}
return "";
}
void TCPDumper::ipDump |
( |
const char * |
label, |
|
|
IPDatagram * |
dgram, |
|
|
const char * |
comment = NULL |
|
) |
| |
Referenced by TCPDump::handleMessage().
{
if (dynamic_cast<SCTPMessage *>(dgram->getEncapsulatedPacket()))
{
SCTPMessage *sctpmsg = check_and_cast<SCTPMessage *>(dgram->getEncapsulatedPacket());
if (dgram->hasBitError())
sctpmsg->setBitError(true);
sctpDump(label, sctpmsg, dgram->getSrcAddress().str(), dgram->getDestAddress().str(), comment);
}
else
delete dgram;
}
void TCPDumper::sctpDump |
( |
const char * |
label, |
|
|
SCTPMessage * |
sctpmsg, |
|
|
const std::string & |
srcAddr, |
|
|
const std::string & |
destAddr, |
|
|
const char * |
comment = NULL |
|
) |
| |
Referenced by TCPDump::handleMessage(), ipDump(), and udpDump().
{
std::ostream& out = *outp;
uint32 numberOfChunks;
SCTPChunk* chunk;
uint8 type;
char buf[30];
sprintf(buf,"[%.3f%s] ", simulation.getSimTime().dbl(), label);
out << buf;
out << srcAddr << "." << sctpmsg->getSrcPort() << " > ";
out << destAddr << "." << sctpmsg->getDestPort() << ": ";
if (sctpmsg->hasBitError())
{
sctpmsg->setChecksumOk(false);
}
numberOfChunks = sctpmsg->getChunksArraySize();
out << "numberOfChunks="<<numberOfChunks<<" VTag="<<sctpmsg->getTag()<<"\n";
if (sctpmsg->hasBitError())
out << "Packet has bit error!!\n";
for (uint32 i=0; i<numberOfChunks; i++)
{
chunk = (SCTPChunk*)sctpmsg->getChunks(i);
type = chunk->getChunkType();
switch (type)
{
case INIT:
out << "INIT ";
break;
case INIT_ACK:
out << "INIT_ACK ";
break;
case COOKIE_ECHO:
out << "COOKIE_ECHO ";
break;
case COOKIE_ACK:
out << "COOKIE_ACK ";
break;
case DATA:
out << "DATA ";
break;
case SACK:
out << "SACK ";
break;
case HEARTBEAT:
out << "HEARTBEAT ";
break;
case HEARTBEAT_ACK:
out << "HEARTBEAT_ACK ";
break;
case ABORT:
out << "ABORT ";
break;
case SHUTDOWN:
out << "SHUTDOWN ";
break;
case SHUTDOWN_ACK:
out << "SHUTDOWN_ACK ";
break;
case SHUTDOWN_COMPLETE:
out << "SHUTDOWN_COMPLETE ";
break;
case ERRORTYPE:
out << "ERROR";
break;
}
}
if (verbosity >= 1)
{
out << endl;
for (uint32 i=0; i<numberOfChunks; i++)
{
chunk = (SCTPChunk*)sctpmsg->getChunks(i);
type = chunk->getChunkType();
sprintf(buf, " %3u: ", i + 1);
out << buf;
switch (type)
{
case INIT:
{
SCTPInitChunk* initChunk;
initChunk = check_and_cast<SCTPInitChunk *>(chunk);
out << "INIT[InitiateTag=";
out << initChunk->getInitTag();
out << "; a_rwnd=";
out << initChunk->getA_rwnd();
out << "; OS=";
out << initChunk->getNoOutStreams();
out << "; IS=";
out << initChunk->getNoInStreams();
out << "; InitialTSN=";
out << initChunk->getInitTSN();
if (initChunk->getAddressesArraySize() > 0)
{
out <<"; Addresses=";
for (uint32 i = 0; i < initChunk->getAddressesArraySize(); i++)
{
if (i > 0)
out << ",";
if (initChunk->getAddresses(i).isIPv6())
out << initChunk->getAddresses(i).str();
else
out << initChunk->getAddresses(i);
}
}
out <<"]";
break;
}
case INIT_ACK:
{
SCTPInitAckChunk* initackChunk;
initackChunk = check_and_cast<SCTPInitAckChunk *>(chunk);
out << "INIT_ACK[InitiateTag=";
out << initackChunk->getInitTag();
out << "; a_rwnd=";
out << initackChunk->getA_rwnd();
out << "; OS=";
out << initackChunk->getNoOutStreams();
out << "; IS=";
out << initackChunk->getNoInStreams();
out << "; InitialTSN=";
out << initackChunk->getInitTSN();
out << "; CookieLength=";
out << initackChunk->getCookieArraySize();
if (initackChunk->getAddressesArraySize() > 0)
{
out <<"; Addresses=";
for (uint32 i = 0; i < initackChunk->getAddressesArraySize(); i++)
{
if (i > 0)
out << ",";
out << initackChunk->getAddresses(i);
}
}
out <<"]";
break;
}
case COOKIE_ECHO:
out << "COOKIE_ECHO[CookieLength=";
out << chunk->getBitLength()/8 - 4;
out <<"]";
break;
case COOKIE_ACK:
out << "COOKIE_ACK ";
break;
case DATA:
{
SCTPDataChunk* dataChunk;
dataChunk = check_and_cast<SCTPDataChunk *>(chunk);
out << "DATA[TSN=";
out << dataChunk->getTsn();
out << "; SID=";
out << dataChunk->getSid();
out << "; SSN=";
out << dataChunk->getSsn();
out << "; PPID=";
out << dataChunk->getPpid();
out << "; PayloadLength=";
out << dataChunk->getBitLength()/8 - 16;
out <<"]";
break;
}
case SACK:
{
SCTPSackChunk* sackChunk;
sackChunk = check_and_cast<SCTPSackChunk *>(chunk);
out << "SACK[CumTSNAck=";
out << sackChunk->getCumTsnAck();
out << "; a_rwnd=";
out << sackChunk->getA_rwnd();
if (sackChunk->getGapStartArraySize() > 0)
{
out <<"; Gaps=";
for (uint32 i = 0; i < sackChunk->getGapStartArraySize(); i++)
{
if (i > 0)
out << ", ";
out << sackChunk->getGapStart(i) << "-" << sackChunk->getGapStop(i);
}
}
if (sackChunk->getDupTsnsArraySize() > 0)
{
out <<"; Dups=";
for (uint32 i = 0; i < sackChunk->getDupTsnsArraySize(); i++)
{
if (i > 0)
out << ", ";
out << sackChunk->getDupTsns(i);
}
}
out <<"]";
break;
}
case HEARTBEAT:
SCTPHeartbeatChunk* heartbeatChunk;
heartbeatChunk = check_and_cast<SCTPHeartbeatChunk *>(chunk);
out << "HEARTBEAT[InfoLength=";
out << chunk->getBitLength()/8 - 4;
out << "; time=";
out << heartbeatChunk->getTimeField();
out <<"]";
break;
case HEARTBEAT_ACK:
out << "HEARTBEAT_ACK[InfoLength=";
out << chunk->getBitLength()/8 - 4;
out <<"]";
break;
case ABORT:
SCTPAbortChunk* abortChunk;
abortChunk = check_and_cast<SCTPAbortChunk *>(chunk);
out << "ABORT[T-Bit=";
out << abortChunk->getT_Bit();
out << "]";
break;
case SHUTDOWN:
SCTPShutdownChunk* shutdown;
shutdown = check_and_cast<SCTPShutdownChunk *>(chunk);
out << "SHUTDOWN[CumTSNAck=";
out << shutdown->getCumTsnAck();
out << "]";
break;
case SHUTDOWN_ACK:
out << "SHUTDOWN_ACK ";
break;
case SHUTDOWN_COMPLETE:
out << "SHUTDOWN_COMPLETE ";
break;
case ERRORTYPE:
{
SCTPErrorChunk* errorChunk;
errorChunk = check_and_cast<SCTPErrorChunk*>(chunk);
uint32 numberOfParameters = errorChunk->getParametersArraySize();
uint32 parameterType;
for (uint32 i=0; i<numberOfParameters; i++)
{
SCTPParameter* param = (SCTPParameter*)errorChunk->getParameters(i);
parameterType = param->getParameterType();
}
break;
}
}
out << endl;
}
}
if (comment)
out << "# " << comment;
out << endl;
}
void TCPDumper::setVerbosity |
( |
const int32 |
verbosityLevel | ) |
[inline] |
void TCPDumper::tcpDump |
( |
bool |
l2r, |
|
|
const char * |
label, |
|
|
IPDatagram * |
dgram, |
|
|
const char * |
comment = NULL |
|
) |
| |
Referenced by dumpIPv6(), and TCPDump::handleMessage().
{
cMessage *encapmsg = dgram->getEncapsulatedPacket();
if (dynamic_cast<TCPSegment *>(encapmsg))
{
tcpDump(l2r, label, (TCPSegment *)encapmsg, dgram->getSrcAddress().str(), dgram->getDestAddress().str(), comment);
}
else
{
std::ostream& out = *outp;
char buf[30];
sprintf(buf,"[%.3f%s] ", SIMTIME_DBL(simTime()), label);
out << buf;
out << "? " << encapmsg->getClassName() << " \"" << encapmsg->getName() << "\"\n";
}
}
void TCPDumper::tcpDump |
( |
bool |
l2r, |
|
|
const char * |
label, |
|
|
TCPSegment * |
tcpseg, |
|
|
const std::string & |
srcAddr, |
|
|
const std::string & |
destAddr, |
|
|
const char * |
comment = NULL |
|
) |
| |
{
std::ostream& out = *outp;
char buf[30];
sprintf(buf,"[%.3f%s] ", SIMTIME_DBL(simTime()), label);
out << buf;
if (l2r)
{
out << srcAddr << "." << tcpseg->getSrcPort() << " > ";
out << destAddr << "." << tcpseg->getDestPort() << ": ";
}
else
{
out << destAddr << "." << tcpseg->getDestPort() << " < ";
out << srcAddr << "." << tcpseg->getSrcPort() << ": ";
}
bool flags = false;
if (tcpseg->getUrgBit()) {flags=true; out << "U ";}
if (tcpseg->getAckBit()) {flags=true; out << "A ";}
if (tcpseg->getPshBit()) {flags=true; out << "P ";}
if (tcpseg->getRstBit()) {flags=true; out << "R ";}
if (tcpseg->getSynBit()) {flags=true; out << "S ";}
if (tcpseg->getFinBit()) {flags=true; out << "F ";}
if (!flags) {out << ". ";}
if (tcpseg->getPayloadLength()>0 || tcpseg->getSynBit())
{
out << tcpseg->getSequenceNo() << ":" << tcpseg->getSequenceNo()+tcpseg->getPayloadLength();
out << "(" << tcpseg->getPayloadLength() << ") ";
}
if (tcpseg->getAckBit())
out << "ack " << tcpseg->getAckNo() << " ";
out << "win " << tcpseg->getWindow() << " ";
if (tcpseg->getUrgBit())
out << "urg " << tcpseg->getUrgentPointer() << " ";
if (tcpseg->getHeaderLength() > 20)
{
std::string direction = "sent";
if (l2r)
{direction = "received";}
unsigned short numOptions = tcpseg->getOptionsArraySize();
out << "\nTCP Header Option(s) " << direction << ":\n";
for (int i=0; i<numOptions; i++)
{
TCPOption option = tcpseg->getOptions(i);
unsigned short kind = option.getKind();
unsigned short length = option.getLength();
out << (i+1) << ". option kind=" << kind << " length=" << length << "\n";
}
}
if (comment)
out << "# " << comment;
out << endl;
}
void TCPDumper::udpDump |
( |
bool |
l2r, |
|
|
const char * |
label, |
|
|
IPDatagram * |
dgram, |
|
|
const char * |
comment |
|
) |
| |
Referenced by TCPDump::handleMessage().
{
cMessage *encapmsg = dgram->getEncapsulatedPacket();
if (dynamic_cast<UDPPacket *>(encapmsg))
{
std::ostream& out = *outp;
char buf[30];
sprintf(buf,"[%.3f%s] ", simulation.getSimTime().dbl(), label);
out << buf;
UDPPacket* udppkt = check_and_cast<UDPPacket*>(encapmsg);
if (l2r)
{
out << dgram->getSrcAddress().str() << "." << udppkt->getSourcePort() << " > ";
out << dgram->getDestAddress().str() << "." << udppkt->getDestinationPort() << ": ";
}
else
{
out << dgram->getDestAddress().str() << "." << udppkt->getDestinationPort() << " < ";
out << dgram->getSrcAddress().str() << "." << udppkt->getSourcePort() << ": ";
}
out << "UDP: Payload length=" << udppkt->getByteLength()-8 << endl;
if (udppkt->getSourcePort()==9899 || udppkt->getDestinationPort() == 9899)
{
if (dynamic_cast<SCTPMessage *>(udppkt->getEncapsulatedPacket()))
sctpDump("", (SCTPMessage *)(udppkt->getEncapsulatedPacket()), std::string(l2r?"A":"B"),std::string(l2r?"B":"A"));
}
}
}
Member Data Documentation
The documentation for this class was generated from the following files: