|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright (C) 2005 Michael Tuexen 00003 // Copyright (C) 2008 Irene Ruengeler 00004 // Copyright (C) 2009 Thomas Dreibholz 00005 // Copyright (C) 2009 Thomas Reschka 00006 // 00007 // This program is free software; you can redistribute it and/or 00008 // modify it under the terms of the GNU Lesser General Public License 00009 // as published by the Free Software Foundation; either version 2 00010 // of the License, or (at your option) any later version. 00011 // 00012 // This program is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU Lesser General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU Lesser General Public License 00018 // along with this program; if not, see <http://www.gnu.org/licenses/>. 00019 // 00020 00021 00022 #include "TCPDump.h" 00023 #include "IPControlInfo_m.h" 00024 #include "SCTPMessage.h" 00025 #include "SCTPAssociation.h" 00026 #include "IPSerializer.h" 00027 #include "ICMPMessage.h" 00028 #include "UDPPacket_m.h" 00029 00030 #if !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32) && !defined(__CYGWIN__) && !defined(_WIN64) 00031 #include <netinet/in.h> // htonl, ntohl, ... 00032 #endif 00033 00034 #define MAXBUFLENGTH 65536 00035 00036 TCPDumper::TCPDumper(std::ostream& out) 00037 { 00038 outp = &out; 00039 } 00040 00041 TCPDumper::~TCPDumper() 00042 { 00043 } 00044 00045 void TCPDumper::ipDump(const char *label, IPDatagram *dgram, const char *comment) 00046 { 00047 if (dynamic_cast<SCTPMessage *>(dgram->getEncapsulatedPacket())) 00048 { 00049 SCTPMessage *sctpmsg = check_and_cast<SCTPMessage *>(dgram->getEncapsulatedPacket()); 00050 if (dgram->hasBitError()) 00051 sctpmsg->setBitError(true); 00052 sctpDump(label, sctpmsg, dgram->getSrcAddress().str(), dgram->getDestAddress().str(), comment); 00053 } 00054 else 00055 delete dgram; 00056 } 00057 00058 void TCPDumper::sctpDump(const char *label, SCTPMessage *sctpmsg, const std::string& srcAddr, const std::string& destAddr, const char *comment) 00059 { 00060 std::ostream& out = *outp; 00061 uint32 numberOfChunks; 00062 SCTPChunk* chunk; 00063 uint8 type; 00064 // seq and time (not part of the tcpdump format) 00065 char buf[30]; 00066 sprintf(buf,"[%.3f%s] ", simulation.getSimTime().dbl(), label); 00067 out << buf; 00068 00069 // src/dest 00070 out << srcAddr << "." << sctpmsg->getSrcPort() << " > "; 00071 00072 out << destAddr << "." << sctpmsg->getDestPort() << ": "; 00073 if (sctpmsg->hasBitError()) 00074 { 00075 sctpmsg->setChecksumOk(false); 00076 } 00077 numberOfChunks = sctpmsg->getChunksArraySize(); 00078 out << "numberOfChunks="<<numberOfChunks<<" VTag="<<sctpmsg->getTag()<<"\n"; 00079 if (sctpmsg->hasBitError()) 00080 out << "Packet has bit error!!\n"; 00081 for (uint32 i=0; i<numberOfChunks; i++) 00082 { 00083 chunk = (SCTPChunk*)sctpmsg->getChunks(i); 00084 type = chunk->getChunkType(); 00085 switch (type) 00086 { 00087 case INIT: 00088 out << "INIT "; 00089 break; 00090 case INIT_ACK: 00091 out << "INIT_ACK "; 00092 break; 00093 case COOKIE_ECHO: 00094 out << "COOKIE_ECHO "; 00095 break; 00096 case COOKIE_ACK: 00097 out << "COOKIE_ACK "; 00098 break; 00099 case DATA: 00100 out << "DATA "; 00101 break; 00102 case SACK: 00103 out << "SACK "; 00104 break; 00105 case HEARTBEAT: 00106 out << "HEARTBEAT "; 00107 break; 00108 case HEARTBEAT_ACK: 00109 out << "HEARTBEAT_ACK "; 00110 break; 00111 case ABORT: 00112 out << "ABORT "; 00113 break; 00114 case SHUTDOWN: 00115 out << "SHUTDOWN "; 00116 break; 00117 case SHUTDOWN_ACK: 00118 out << "SHUTDOWN_ACK "; 00119 break; 00120 case SHUTDOWN_COMPLETE: 00121 out << "SHUTDOWN_COMPLETE "; 00122 break; 00123 case ERRORTYPE: 00124 out << "ERROR"; 00125 break; 00126 00127 } 00128 } 00129 00130 if (verbosity >= 1) 00131 { 00132 out << endl; 00133 for (uint32 i=0; i<numberOfChunks; i++) 00134 { 00135 chunk = (SCTPChunk*)sctpmsg->getChunks(i); 00136 type = chunk->getChunkType(); 00137 00138 sprintf(buf, " %3u: ", i + 1); 00139 out << buf; 00140 switch (type) 00141 { 00142 case INIT: 00143 { 00144 SCTPInitChunk* initChunk; 00145 initChunk = check_and_cast<SCTPInitChunk *>(chunk); 00146 out << "INIT[InitiateTag="; 00147 out << initChunk->getInitTag(); 00148 out << "; a_rwnd="; 00149 out << initChunk->getA_rwnd(); 00150 out << "; OS="; 00151 out << initChunk->getNoOutStreams(); 00152 out << "; IS="; 00153 out << initChunk->getNoInStreams(); 00154 out << "; InitialTSN="; 00155 out << initChunk->getInitTSN(); 00156 if (initChunk->getAddressesArraySize() > 0) 00157 { 00158 out <<"; Addresses="; 00159 for (uint32 i = 0; i < initChunk->getAddressesArraySize(); i++) 00160 { 00161 if (i > 0) 00162 out << ","; 00163 if (initChunk->getAddresses(i).isIPv6()) 00164 out << initChunk->getAddresses(i).str(); 00165 else 00166 out << initChunk->getAddresses(i); 00167 } 00168 } 00169 00170 out <<"]"; 00171 break; 00172 } 00173 case INIT_ACK: 00174 { 00175 SCTPInitAckChunk* initackChunk; 00176 initackChunk = check_and_cast<SCTPInitAckChunk *>(chunk); 00177 out << "INIT_ACK[InitiateTag="; 00178 out << initackChunk->getInitTag(); 00179 out << "; a_rwnd="; 00180 out << initackChunk->getA_rwnd(); 00181 out << "; OS="; 00182 out << initackChunk->getNoOutStreams(); 00183 out << "; IS="; 00184 out << initackChunk->getNoInStreams(); 00185 out << "; InitialTSN="; 00186 out << initackChunk->getInitTSN(); 00187 out << "; CookieLength="; 00188 out << initackChunk->getCookieArraySize(); 00189 if (initackChunk->getAddressesArraySize() > 0) 00190 { 00191 out <<"; Addresses="; 00192 for (uint32 i = 0; i < initackChunk->getAddressesArraySize(); i++) 00193 { 00194 if (i > 0) 00195 out << ","; 00196 out << initackChunk->getAddresses(i); 00197 } 00198 } 00199 out <<"]"; 00200 break; 00201 } 00202 case COOKIE_ECHO: 00203 out << "COOKIE_ECHO[CookieLength="; 00204 out << chunk->getBitLength()/8 - 4; 00205 out <<"]"; 00206 break; 00207 case COOKIE_ACK: 00208 out << "COOKIE_ACK "; 00209 break; 00210 case DATA: 00211 { 00212 SCTPDataChunk* dataChunk; 00213 dataChunk = check_and_cast<SCTPDataChunk *>(chunk); 00214 out << "DATA[TSN="; 00215 out << dataChunk->getTsn(); 00216 out << "; SID="; 00217 out << dataChunk->getSid(); 00218 out << "; SSN="; 00219 out << dataChunk->getSsn(); 00220 out << "; PPID="; 00221 out << dataChunk->getPpid(); 00222 out << "; PayloadLength="; 00223 out << dataChunk->getBitLength()/8 - 16; 00224 out <<"]"; 00225 break; 00226 } 00227 case SACK: 00228 { 00229 SCTPSackChunk* sackChunk; 00230 sackChunk = check_and_cast<SCTPSackChunk *>(chunk); 00231 out << "SACK[CumTSNAck="; 00232 out << sackChunk->getCumTsnAck(); 00233 out << "; a_rwnd="; 00234 out << sackChunk->getA_rwnd(); 00235 if (sackChunk->getGapStartArraySize() > 0) 00236 { 00237 out <<"; Gaps="; 00238 for (uint32 i = 0; i < sackChunk->getGapStartArraySize(); i++) 00239 { 00240 if (i > 0) 00241 out << ", "; 00242 out << sackChunk->getGapStart(i) << "-" << sackChunk->getGapStop(i); 00243 } 00244 } 00245 if (sackChunk->getDupTsnsArraySize() > 0) 00246 { 00247 out <<"; Dups="; 00248 for (uint32 i = 0; i < sackChunk->getDupTsnsArraySize(); i++) 00249 { 00250 if (i > 0) 00251 out << ", "; 00252 out << sackChunk->getDupTsns(i); 00253 } 00254 } 00255 out <<"]"; 00256 break; 00257 } 00258 case HEARTBEAT: 00259 SCTPHeartbeatChunk* heartbeatChunk; 00260 heartbeatChunk = check_and_cast<SCTPHeartbeatChunk *>(chunk); 00261 out << "HEARTBEAT[InfoLength="; 00262 out << chunk->getBitLength()/8 - 4; 00263 out << "; time="; 00264 out << heartbeatChunk->getTimeField(); 00265 out <<"]"; 00266 break; 00267 case HEARTBEAT_ACK: 00268 out << "HEARTBEAT_ACK[InfoLength="; 00269 out << chunk->getBitLength()/8 - 4; 00270 out <<"]"; 00271 break; 00272 case ABORT: 00273 SCTPAbortChunk* abortChunk; 00274 abortChunk = check_and_cast<SCTPAbortChunk *>(chunk); 00275 out << "ABORT[T-Bit="; 00276 out << abortChunk->getT_Bit(); 00277 out << "]"; 00278 break; 00279 case SHUTDOWN: 00280 SCTPShutdownChunk* shutdown; 00281 shutdown = check_and_cast<SCTPShutdownChunk *>(chunk); 00282 out << "SHUTDOWN[CumTSNAck="; 00283 out << shutdown->getCumTsnAck(); 00284 out << "]"; 00285 break; 00286 case SHUTDOWN_ACK: 00287 out << "SHUTDOWN_ACK "; 00288 break; 00289 case SHUTDOWN_COMPLETE: 00290 out << "SHUTDOWN_COMPLETE "; 00291 break; 00292 case ERRORTYPE: 00293 { 00294 SCTPErrorChunk* errorChunk; 00295 errorChunk = check_and_cast<SCTPErrorChunk*>(chunk); 00296 uint32 numberOfParameters = errorChunk->getParametersArraySize(); 00297 uint32 parameterType; 00298 for (uint32 i=0; i<numberOfParameters; i++) 00299 { 00300 SCTPParameter* param = (SCTPParameter*)errorChunk->getParameters(i); 00301 parameterType = param->getParameterType(); 00302 } 00303 00304 break; 00305 } 00306 00307 } 00308 out << endl; 00309 } 00310 } 00311 // comment 00312 if (comment) 00313 out << "# " << comment; 00314 00315 out << endl; 00316 } 00317 00318 TCPDump::~TCPDump() 00319 { 00320 } 00321 00322 const char *TCPDumper::intToChunk(int32 type) 00323 { 00324 switch (type) 00325 { 00326 case 0: return "DATA"; 00327 case 1: return "INIT"; 00328 case 2: return "INIT_ACK"; 00329 case 3: return "SACK"; 00330 case 4: return "HEARTBEAT"; 00331 case 5: return "HEARTBEAT_ACK"; 00332 case 6: return "ABORT"; 00333 case 7: return "SHUTDOWN"; 00334 case 8: return "SHUTDOWN_ACK"; 00335 case 9: return "ERRORTYPE"; 00336 case 10: return "COOKIE_ECHO"; 00337 case 11: return "COOKIE_ACK"; 00338 case 14: return "SHUTDOWN_COMPLETE"; 00339 } 00340 return ""; 00341 } 00342 00343 void TCPDumper::dump(const char *label, const char *msg) 00344 { 00345 std::ostream& out = *outp; 00346 00347 // seq and time (not part of the tcpdump format) 00348 char buf[30]; 00349 sprintf(buf,"[%.3f%s] ", simulation.getSimTime().dbl(), label); 00350 out << buf; 00351 00352 out << msg << "\n"; 00353 } 00354 00355 //---- 00356 00357 Define_Module(TCPDump); 00358 00359 TCPDump::TCPDump() : cSimpleModule(), tcpdump(ev.getOStream()) 00360 { 00361 00362 00363 } 00364 00365 void TCPDumper::udpDump(bool l2r, const char *label, IPDatagram *dgram, const char *comment) 00366 { 00367 cMessage *encapmsg = dgram->getEncapsulatedPacket(); 00368 if (dynamic_cast<UDPPacket *>(encapmsg)) 00369 { 00370 std::ostream& out = *outp; 00371 00372 // seq and time (not part of the tcpdump format) 00373 char buf[30]; 00374 sprintf(buf,"[%.3f%s] ", simulation.getSimTime().dbl(), label); 00375 out << buf; 00376 UDPPacket* udppkt = check_and_cast<UDPPacket*>(encapmsg); 00377 00378 // src/dest 00379 if (l2r) 00380 { 00381 out << dgram->getSrcAddress().str() << "." << udppkt->getSourcePort() << " > "; 00382 out << dgram->getDestAddress().str() << "." << udppkt->getDestinationPort() << ": "; 00383 } 00384 else 00385 { 00386 out << dgram->getDestAddress().str() << "." << udppkt->getDestinationPort() << " < "; 00387 out << dgram->getSrcAddress().str() << "." << udppkt->getSourcePort() << ": "; 00388 } 00389 00390 //out << endl; 00391 out << "UDP: Payload length=" << udppkt->getByteLength()-8 << endl; 00392 if (udppkt->getSourcePort()==9899 || udppkt->getDestinationPort() == 9899) 00393 { 00394 if (dynamic_cast<SCTPMessage *>(udppkt->getEncapsulatedPacket())) 00395 sctpDump("", (SCTPMessage *)(udppkt->getEncapsulatedPacket()), std::string(l2r?"A":"B"),std::string(l2r?"B":"A")); 00396 } 00397 } 00398 } 00399 00400 void TCPDumper::tcpDump(bool l2r, const char *label, IPDatagram *dgram, const char *comment) 00401 { 00402 cMessage *encapmsg = dgram->getEncapsulatedPacket(); 00403 if (dynamic_cast<TCPSegment *>(encapmsg)) 00404 { 00405 // if TCP, dump as TCP 00406 tcpDump(l2r, label, (TCPSegment *)encapmsg, dgram->getSrcAddress().str(), dgram->getDestAddress().str(), comment); 00407 } 00408 else 00409 { 00410 // some other packet, dump what we can 00411 std::ostream& out = *outp; 00412 00413 // seq and time (not part of the tcpdump format) 00414 char buf[30]; 00415 sprintf(buf,"[%.3f%s] ", SIMTIME_DBL(simTime()), label); 00416 out << buf; 00417 00418 // packet class and name 00419 out << "? " << encapmsg->getClassName() << " \"" << encapmsg->getName() << "\"\n"; 00420 } 00421 } 00422 00423 //FIXME: Temporary hack for Ipv6 support 00424 void TCPDumper::dumpIPv6(bool l2r, const char *label, IPv6Datagram_Base *dgram, const char *comment) 00425 { 00426 cMessage *encapmsg = dgram->getEncapsulatedPacket(); 00427 if (dynamic_cast<TCPSegment *>(encapmsg)) 00428 { 00429 // if TCP, dump as TCP 00430 tcpDump(l2r, label, (TCPSegment *)encapmsg, dgram->getSrcAddress().str(), dgram->getDestAddress().str(), comment); 00431 } 00432 else 00433 { 00434 // some other packet, dump what we can 00435 std::ostream& out = *outp; 00436 00437 // seq and time (not part of the tcpdump format) 00438 char buf[30]; 00439 sprintf(buf,"[%.3f%s] ", SIMTIME_DBL(simTime()), label); 00440 out << buf; 00441 00442 // packet class and name 00443 out << "? " << encapmsg->getClassName() << " \"" << encapmsg->getName() << "\"\n"; 00444 } 00445 } 00446 00447 void TCPDumper::tcpDump(bool l2r, const char *label, TCPSegment *tcpseg, const std::string& srcAddr, const std::string& destAddr, const char *comment) 00448 { 00449 std::ostream& out = *outp; 00450 00451 // seq and time (not part of the tcpdump format) 00452 char buf[30]; 00453 sprintf(buf,"[%.3f%s] ", SIMTIME_DBL(simTime()), label); 00454 out << buf; 00455 // src/dest ports 00456 if (l2r) 00457 { 00458 out << srcAddr << "." << tcpseg->getSrcPort() << " > "; 00459 out << destAddr << "." << tcpseg->getDestPort() << ": "; 00460 } 00461 else 00462 { 00463 out << destAddr << "." << tcpseg->getDestPort() << " < "; 00464 out << srcAddr << "." << tcpseg->getSrcPort() << ": "; 00465 } 00466 00467 // flags 00468 bool flags = false; 00469 if (tcpseg->getUrgBit()) {flags=true; out << "U ";} 00470 if (tcpseg->getAckBit()) {flags=true; out << "A ";} 00471 if (tcpseg->getPshBit()) {flags=true; out << "P ";} 00472 if (tcpseg->getRstBit()) {flags=true; out << "R ";} 00473 if (tcpseg->getSynBit()) {flags=true; out << "S ";} 00474 if (tcpseg->getFinBit()) {flags=true; out << "F ";} 00475 if (!flags) {out << ". ";} 00476 00477 // data-seqno 00478 if (tcpseg->getPayloadLength()>0 || tcpseg->getSynBit()) 00479 { 00480 out << tcpseg->getSequenceNo() << ":" << tcpseg->getSequenceNo()+tcpseg->getPayloadLength(); 00481 out << "(" << tcpseg->getPayloadLength() << ") "; 00482 } 00483 00484 // ack 00485 if (tcpseg->getAckBit()) 00486 out << "ack " << tcpseg->getAckNo() << " "; 00487 00488 // window 00489 out << "win " << tcpseg->getWindow() << " "; 00490 00491 // urgent 00492 if (tcpseg->getUrgBit()) 00493 out << "urg " << tcpseg->getUrgentPointer() << " "; 00494 00495 // options present? 00496 if (tcpseg->getHeaderLength() > 20) 00497 { 00498 std::string direction = "sent"; 00499 if (l2r) // change direction 00500 {direction = "received";} 00501 00502 unsigned short numOptions = tcpseg->getOptionsArraySize(); 00503 out << "\nTCP Header Option(s) " << direction << ":\n"; 00504 for (int i=0; i<numOptions; i++) 00505 { 00506 TCPOption option = tcpseg->getOptions(i); 00507 unsigned short kind = option.getKind(); 00508 unsigned short length = option.getLength(); 00509 out << (i+1) << ". option kind=" << kind << " length=" << length << "\n"; 00510 } 00511 } 00512 00513 // comment 00514 if (comment) 00515 out << "# " << comment; 00516 00517 out << endl; 00518 } 00519 00520 void TCPDump::initialize() 00521 { 00522 struct pcap_hdr fh; 00523 const char* file = this->par("dumpFile"); 00524 snaplen = this->par("snaplen"); 00525 tcpdump.setVerbosity(par("verbosity")); 00526 00527 00528 if (strcmp(file,"")!=0) 00529 { 00530 tcpdump.dumpfile = fopen(file, "wb"); 00531 if (!tcpdump.dumpfile) 00532 { 00533 fprintf(stderr, "Cannot open file [%s] for writing: %s\n", file, strerror(errno)); 00534 exit(-1); 00535 } 00536 00537 fh.magic = PCAP_MAGIC; 00538 fh.version_major = 2; 00539 fh.version_minor = 4; 00540 fh.thiszone = 0; 00541 fh.sigfigs = 0; 00542 fh.snaplen = snaplen; 00543 fh.network = 0; 00544 fwrite(&fh, sizeof(fh), 1, tcpdump.dumpfile); 00545 } 00546 else 00547 tcpdump.dumpfile = NULL; 00548 } 00549 00550 void TCPDump::handleMessage(cMessage *msg) 00551 { 00552 00553 if (!ev.disable_tracing) 00554 { 00555 bool l2r; 00556 00557 if (dynamic_cast<IPDatagram *>(msg)) 00558 { 00559 if (((IPDatagram *)msg)->getTransportProtocol()==132) 00560 { 00561 tcpdump.ipDump("", (IPDatagram *)msg); 00562 } 00563 else 00564 { 00565 if (PK(msg)->hasBitError()) 00566 { 00567 delete msg; 00568 return; 00569 } 00570 l2r = msg->arrivedOn("in1"); 00571 if (((IPDatagram *)msg)->getTransportProtocol()==6) 00572 { 00573 tcpdump.tcpDump(l2r, "", (IPDatagram *)msg, ""); 00574 } 00575 else if (((IPDatagram *)msg)->getTransportProtocol()==17) 00576 tcpdump.udpDump(l2r, "", (IPDatagram *)msg, ""); 00577 } 00578 } 00579 else if (dynamic_cast<SCTPMessage *>(msg)) 00580 { 00581 l2r = msg->arrivedOn("in1"); 00582 tcpdump.sctpDump("", (SCTPMessage *)msg, std::string(l2r?"A":"B"),std::string(l2r?"B":"A")); 00583 } 00584 else if (dynamic_cast<TCPSegment *>(msg)) 00585 { 00586 if (PK(msg)->hasBitError()) 00587 { 00588 delete msg; 00589 return; 00590 } 00591 l2r = msg->arrivedOn("in1"); 00592 tcpdump.tcpDump(l2r, "", (TCPSegment *)msg, std::string(l2r?"A":"B"),std::string(l2r?"B":"A")); 00593 } 00594 else if (dynamic_cast<ICMPMessage *>(msg)) 00595 { 00596 if (PK(msg)->hasBitError()) 00597 { 00598 delete msg; 00599 return; 00600 } 00601 std::cout<<"ICMPMessage\n"; 00602 } 00603 else 00604 { 00605 // search for encapsulated IP[v6]Datagram in it 00606 cPacket *encapmsg = PK(msg); 00607 while (encapmsg && dynamic_cast<IPDatagram *>(encapmsg)==NULL && dynamic_cast<IPv6Datagram_Base *>(encapmsg)==NULL) 00608 encapmsg = encapmsg->getEncapsulatedPacket(); 00609 l2r = msg->arrivedOn("in1"); 00610 if (!encapmsg) 00611 { 00612 //We do not want this to end in an error if EtherAutoconf messages 00613 //are passed, so just print a warning. -WEI 00614 EV << "CANNOT DECODE: packet " << msg->getName() << " doesn't contain either IP or IPv6 Datagram\n"; 00615 } 00616 else 00617 { 00618 if (dynamic_cast<IPDatagram *>(encapmsg)) 00619 tcpdump.tcpDump(l2r, "", (IPDatagram *)encapmsg); 00620 else if (dynamic_cast<IPv6Datagram_Base *>(encapmsg)) 00621 tcpdump.dumpIPv6(l2r, "", (IPv6Datagram_Base *)encapmsg); 00622 else 00623 ASSERT(0); // cannot get here 00624 } 00625 } 00626 } 00627 00628 00629 if (tcpdump.dumpfile!=NULL && dynamic_cast<IPDatagram *>(msg)) 00630 { 00631 uint8 buf[MAXBUFLENGTH]; 00632 memset((void*)&buf, 0, sizeof(buf)); 00633 00634 const simtime_t stime = simulation.getSimTime(); 00635 // Write PCap header 00636 00637 struct pcaprec_hdr ph; 00638 ph.ts_sec = (int32)stime.dbl(); 00639 ph.ts_usec = (uint32)((stime.dbl() - ph.ts_sec)*1000000); 00640 // Write Ethernet header 00641 uint32 hdr = 2; //AF_INET 00642 //We do not want this to end in an error if EtherAutoconf messages 00643 IPDatagram *ipPacket = check_and_cast<IPDatagram *>(msg); 00644 // IP header: 00645 //struct sockaddr_in *to = (struct sockaddr_in*) malloc(sizeof(struct sockaddr_in)); 00646 //int32 tosize = sizeof(struct sockaddr_in); 00647 int32 serialized_ip = IPSerializer().serialize(ipPacket, buf, sizeof(buf)); 00648 ph.incl_len = serialized_ip + sizeof(uint32); 00649 00650 ph.orig_len = ph.incl_len; 00651 fwrite(&ph, sizeof(ph), 1, tcpdump.dumpfile); 00652 fwrite(&hdr, sizeof(uint32), 1, tcpdump.dumpfile); 00653 fwrite(buf, serialized_ip, 1, tcpdump.dumpfile); 00654 } 00655 00656 00657 // forward 00658 int32 index = msg->getArrivalGate()->getIndex(); 00659 int32 id; 00660 if (msg->getArrivalGate()->isName("ifIn")) 00661 id = findGate("out2",index); 00662 else 00663 id = findGate("ifOut",index); 00664 00665 send(msg, id); 00666 } 00667 00668 void TCPDump::finish() 00669 { 00670 tcpdump.dump("", "tcpdump finished"); 00671 if (strcmp(this->par("dumpFile"),"")!=0) 00672 fclose(tcpdump.dumpfile); 00673 } 00674