There is a diff between the original and imported streams. See details to review the diff.
Why a diff? See possible reasons.
\n\n\n\n").arg("https://jump.ostinato.org/pcapdiff")); + diffFile.open(); + diffFile.seek(0); + error.append(QString(diffFile.readAll())); + } + + goto _exit; + } + +_non_pdml: + qDebug("pcap resolution: %s", nsecResolution ? "nsec" : "usec"); + emit status("Reading Packets..."); + emit target(100); // in percentage + pktCount = 1; + while (!fd_.atEnd()) + { + OstProto::Stream *stream = streams.add_stream(); + OstProto::Protocol *proto = stream->add_protocol(); + OstProto::HexDump *hexDump = proto->MutableExtension(OstProto::hexDump); + + proto->mutable_protocol_id()->set_id( + OstProto::Protocol::kHexDumpFieldNumber); + + readPacket(pktHdr, pktBuf); + + // validations on inclLen <= origLen && inclLen <= snapLen + Q_ASSERT(pktHdr.inclLen <= fileHdr.snapLen); // TODO: convert to if + + hexDump->set_content(pktBuf.data(), pktHdr.inclLen); + hexDump->set_pad_until_end(false); + + stream->mutable_stream_id()->set_id(pktCount); + stream->mutable_core()->set_is_enabled(true); + stream->mutable_core()->set_frame_len(pktHdr.inclLen+4); // FCS + + stream->mutable_control()->set_num_packets(1); + + // setup packet rate to the timing in pcap (as close as possible) + // use quint64 rather than double to store micro/nano second as + // it has a larger range (~580 years) and therefore better accuracy + const quint64 kXsecsInSec = nsecResolution ? 1e9 : 1e6; + quint64 xsec = (pktHdr.tsSec*kXsecsInSec + pktHdr.tsUsec); + quint64 delta = xsec - lastXsec; + qDebug("pktCount = %d, delta = %llu", pktCount, delta); + + if ((pktCount != 1) && delta) + stream->mutable_control()->set_packets_per_sec(double(kXsecsInSec)/delta); + + if (prevStream) + prevStream->mutable_control()->CopyFrom(stream->control()); + + lastXsec = xsec; + prevStream = stream; + pktCount++; + byteCount += pktHdr.inclLen + sizeof(pktHdr); + emit progress(int(byteCount*100/byteTotal)); // in percentage + if (stop_) + goto _user_cancel; + } + + isOk = true; + goto _exit; + +_user_cancel: + isOk = true; + goto _exit; + +_diff_fail: + goto _exit; + +_err_unsupported_encap: + error = QString(tr("%1 has non-ethernet encapsulation (%2) which is " + "not supported - Sorry!")) + .arg(QFileInfo(fileName).fileName()).arg(fileHdr.network); + goto _exit; + +_err_unsupported_version: + error = QString(tr("%1 is in PCAP version %2.%3 format which is " + "not supported - Sorry!")) + .arg(fileName).arg(fileHdr.versionMajor).arg(fileHdr.versionMinor); + goto _exit; + +_err_bad_magic: + error = QString(tr("%1 is not a valid PCAP file")).arg(fileName); + goto _exit; + +#if 0 +_err_truncated: + error = QString(tr("%1 is too short")).arg(fileName); + goto _exit; +#endif + +_err_unzip_fail: + goto _exit; + +_err_reading_magic: + error = QString(tr("Unable to read magic from %1")).arg(fileName); + goto _exit; + +_err_convert2pcap: + goto _exit; + +_err_open: + error = QString(tr("Unable to open file: %1")).arg(fileName); + goto _exit; + +_exit: + if (!error.isEmpty()) + qDebug("%s", qPrintable(error)); + file.close(); + return isOk; +} + +/*! + Converts a non-PCAP capture file to standard PCAP file format using tshark + + Returns true if conversion was successful, false otherwise. +*/ +bool PcapFileFormat::convertToStandardPcap( + QString fileName, QString outputFileName, QString &error) +{ + qDebug("converting to PCAP %s", qPrintable(outputFileName)); + emit status("Unsupported format. Converting to standard PCAP format..."); + emit target(0); + + QProcess tshark; + tshark.start(OstProtoLib::tsharkPath(), + QStringList() + << QString("-r%1").arg(fileName) + << "-Fnsecpcap" + << QString("-w%1").arg(outputFileName)); + if (!tshark.waitForStarted(-1)) + { + error.append(QString("Unable to start tshark. Check path in preferences.\n")); + return false; + } + + if (!tshark.waitForFinished(-1)) + { + error.append(QString("Error running tshark\n")); + return false; + } + + return true; +} + +/*! + Reads packet meta data into pktHdr and packet content into buf. + + Returns true if packet is read successfully, false otherwise. +*/ +bool PcapFileFormat::readPacket(PcapPacketHeader &pktHdr, QByteArray &pktBuf) +{ + quint32 len; + + // TODO: chk fd_.status() + + // read PcapPacketHeader + fd_ >> pktHdr.tsSec; + fd_ >> pktHdr.tsUsec; + fd_ >> pktHdr.inclLen; + fd_ >> pktHdr.origLen; + + // TODO: chk fd_.status() + + // XXX: should never be required, but we play safe + if (quint32(pktBuf.size()) < pktHdr.inclLen) + pktBuf.resize(pktHdr.inclLen); + + // read Pkt contents + len = fd_.readRawData(pktBuf.data(), pktHdr.inclLen); // TODO: use while? + + Q_ASSERT(len == pktHdr.inclLen); // TODO: remove assert + pktBuf.resize(len); + + return true; +} + +bool PcapFileFormat::save(const OstProto::StreamConfigList streams, + const QString fileName, QString &error) +{ + bool isOk = false; + QFile file(fileName); + PcapFileHeader fileHdr; + PcapPacketHeader pktHdr; + QByteArray pktBuf; + + if (!file.open(QIODevice::WriteOnly)) + goto _err_open; + + fd_.setDevice(&file); + + fileHdr.magicNumber = kNanoSecondPcapFileMagic; + fileHdr.versionMajor = kPcapFileVersionMajor; + fileHdr.versionMinor = kPcapFileVersionMinor; + fileHdr.thisZone = 0; + fileHdr.sigfigs = 0; + fileHdr.snapLen = kMaxSnapLen; + fileHdr.network = kDltEthernet; + + fd_ << fileHdr.magicNumber; + fd_ << fileHdr.versionMajor; + fd_ << fileHdr.versionMinor; + fd_ << fileHdr.thisZone; + fd_ << fileHdr.sigfigs; + fd_ << fileHdr.snapLen; + fd_ << fileHdr.network; + + pktBuf.resize(kMaxSnapLen); + + emit status("Writing Packets..."); + emit target(streams.stream_size()); + + pktHdr.tsSec = 0; + pktHdr.tsUsec = 0; + for (int i = 0; i < streams.stream_size(); i++) + { + StreamBase s; + + s.setId(i); + s.protoDataCopyFrom(streams.stream(i)); + // TODO: expand frameIndex for each stream + s.frameValue((uchar*)pktBuf.data(), pktBuf.size(), 0); + + pktHdr.inclLen = s.frameProtocolLength(0); // FIXME: stream index = 0 + pktHdr.origLen = s.frameLen() - 4; // FCS; FIXME: Hardcoding + + qDebug("savepcap i=%d, incl/orig len = %d/%d", i, + pktHdr.inclLen, pktHdr.origLen); + + if (pktHdr.inclLen > fileHdr.snapLen) + pktHdr.inclLen = fileHdr.snapLen; + + fd_ << pktHdr.tsSec; + fd_ << pktHdr.tsUsec; + fd_ << pktHdr.inclLen; + fd_ << pktHdr.origLen; + fd_.writeRawData(pktBuf.data(), pktHdr.inclLen); + + if (s.packetRate()) + { + quint64 delta = quint64(1e9/s.packetRate()); + pktHdr.tsSec += delta/quint32(1e9); + pktHdr.tsUsec += delta % quint32(1e9); + } + + if (pktHdr.tsUsec >= quint32(1e9)) + { + pktHdr.tsSec++; + pktHdr.tsUsec -= quint32(1e9); + } + + emit progress(i); + } + + file.close(); + + isOk = true; + goto _exit; + +_err_open: + error = QString(tr("Unable to open file: %1")).arg(fileName); + goto _exit; + +_exit: + return isOk; +} + +QDialog* PcapFileFormat::openOptionsDialog() +{ + return new PcapImportOptionsDialog(&importOptions_); +} + +bool PcapFileFormat::isMyFileFormat(const QString /*fileName*/) +{ + // TODO + return true; +} + +bool PcapFileFormat::isMyFileType(const QString fileType) +{ + if (fileType.startsWith("PCAP")) + return true; + else + return false; +} diff --git a/common/pcapfileformatoptions.h b/common/pcapfileformatoptions.h new file mode 100644 index 0000000..5e8a744 --- /dev/null +++ b/common/pcapfileformatoptions.h @@ -0,0 +1,88 @@ +/* +Copyright (C) 2011 Srivats P. + +This file is part of "Ostinato" + +This is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see