diff --git a/common/pdml_p.cpp b/common/pdml_p.cpp index 4d8eee7..e887f33 100644 --- a/common/pdml_p.cpp +++ b/common/pdml_p.cpp @@ -21,8 +21,10 @@ along with this program. If not, see #include "mac.pb.h" #include "eth2.pb.h" -#include "ip4.pb.h" #include "hexdump.pb.h" +#include "ip4.pb.h" +#include "ip6.pb.h" +#include "tcp.pb.h" #include @@ -85,16 +87,24 @@ void PdmlDefaultProtocol::unknownFieldHandler(QString name, // ---------------------------------------------------------- // PdmlParser::PdmlParser(OstProto::StreamConfigList *streams) { - skipUntilEndOfPacket_ = false; skipCount_ = 0; + currentPdmlProtocol_ = NULL; streams_ = streams; protocolMap_.insert("unknown", new PdmlUnknownProtocol()); protocolMap_.insert("geninfo", new PdmlGenInfoProtocol()); protocolMap_.insert("frame", new PdmlFrameProtocol()); +#if 0 + protocolMap_.insert("fake-field-wrapper", + new PdmlFakeFieldWrapperProtocol()); +#endif +#if 0 protocolMap_.insert("eth", new PdmlEthProtocol()); protocolMap_.insert("ip", new PdmlIp4Protocol()); + protocolMap_.insert("ipv6", new PdmlIp6Protocol()); + protocolMap_.insert("tcp", new PdmlTcpProtocol()); +#endif } PdmlParser::~PdmlParser() @@ -109,12 +119,6 @@ bool PdmlParser::startElement(const QString & /* namespaceURI */, { qDebug("%s (%s)", __FUNCTION__, qName.toAscii().constData()); - if (skipUntilEndOfPacket_) - { - Q_ASSERT(skipCount_ == 0); - goto _exit; - } - if (skipCount_) { skipCount_++; @@ -127,8 +131,6 @@ bool PdmlParser::startElement(const QString & /* namespaceURI */, } else if (qName == "packet") { - Q_ASSERT(skipUntilEndOfPacket_ == false); - // XXX: For now, each packet is converted to a stream currentStream_ = streams_->add_stream(); currentStream_->mutable_stream_id()->set_id(packetCount_); @@ -146,11 +148,11 @@ bool PdmlParser::startElement(const QString & /* namespaceURI */, goto _exit; } - if (protoName == "fake-field-wrapper") - { - skipUntilEndOfPacket_ = true; - goto _exit; - } + // HACK HACK HACK + if (currentPdmlProtocol_ && (currentPdmlProtocol_->ostProtoId() + == OstProto::Protocol::kHexDumpFieldNumber)) + currentPdmlProtocol_->postProtocolHandler(currentStream_); + if (!protocolMap_.contains(protoName)) protoName = "unknown"; // FIXME: change to Ost:Hexdump @@ -161,25 +163,26 @@ bool PdmlParser::startElement(const QString & /* namespaceURI */, int protoId = currentPdmlProtocol_->ostProtoId(); + // PdmlDefaultProtocol => + if (protoId <= 0) + goto _exit; + + OstProto::Protocol *proto = currentStream_->add_protocol(); + + proto->mutable_protocol_id()->set_id(protoId); + + const google::protobuf::Reflection *msgRefl = + proto->GetReflection(); + const google::protobuf::FieldDescriptor *fDesc = + msgRefl->FindKnownExtensionByNumber(protoId); + + // TODO: if !fDesc + // init default values of all fields in protocol + currentProtocolMsg_ = msgRefl->MutableMessage(proto, fDesc); + currentPdmlProtocol_->preProtocolHandler(protoName, attributes, currentStream_); - if (protoId > 0) - { - OstProto::Protocol *proto = currentStream_->add_protocol(); - - proto->mutable_protocol_id()->set_id(protoId); - - const google::protobuf::Reflection *msgRefl = - proto->GetReflection(); - - const google::protobuf::FieldDescriptor *fDesc = - msgRefl->FindKnownExtensionByNumber(protoId); - - // TODO: if !fDesc - // init default values of all fields in protocol - currentProtocolMsg_ = msgRefl->MutableMessage(proto, fDesc); - } } else if (qName == "field") { @@ -191,16 +194,14 @@ bool PdmlParser::startElement(const QString & /* namespaceURI */, } QString name = attributes.value("name"); - int pos = attributes.value("pos").toInt(); - int size = attributes.value("size").toInt(); QString valueStr = attributes.value("value"); + int pos = -1; + int size = -1; - // fields with no name are analysis and should be skipped - if (name.isEmpty()) - { - skipCount_++; - goto _exit; - } + if (!attributes.value("pos").isEmpty()) + pos = attributes.value("pos").toInt(); + if (!attributes.value("size").isEmpty()) + size = attributes.value("size").toInt(); qDebug("\tname:%s, pos:%d, size:%d value:%s", name.toAscii().constData(), @@ -236,6 +237,14 @@ bool PdmlParser::startElement(const QString & /* namespaceURI */, case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: msgRefl->SetUInt64(currentProtocolMsg_, fDesc, valueStr.toULongLong(&isOk, kBaseHex)); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_STRING: + { + QByteArray hexVal = QByteArray::fromHex(valueStr.toUtf8()); + std::string str(hexVal.constData(), hexVal.size()); + msgRefl->SetString(currentProtocolMsg_, fDesc, str); + break; + } default: qDebug("%s: unhandled cpptype = %d", __FUNCTION__, fDesc->cpp_type()); @@ -262,16 +271,21 @@ bool PdmlParser::endElement(const QString & /* namespaceURI */, if (qName == "packet") { + if (currentStream_->core().name().size()) + { + OstProto::Protocol *proto = currentStream_->add_protocol(); + + proto->mutable_protocol_id()->set_id( + OstProto::Protocol::kHexDumpFieldNumber); + + OstProto::HexDump *hexDump = proto->MutableExtension(OstProto::hexDump); + + hexDump->set_content(currentStream_->core().name()); + hexDump->set_pad_until_end(false); + currentStream_->mutable_core()->set_name(""); + } packetCount_++; - if (skipUntilEndOfPacket_) - skipUntilEndOfPacket_ = false; - - goto _exit; - } - - if (skipUntilEndOfPacket_) - { - Q_ASSERT(skipCount_ == 0); + currentPdmlProtocol_ = NULL; goto _exit; } @@ -284,6 +298,7 @@ bool PdmlParser::endElement(const QString & /* namespaceURI */, if (qName == "proto") { currentPdmlProtocol_->postProtocolHandler(currentStream_); + //currentPdmlProtocol_ = NULL; } else if (qName == "field") { @@ -331,14 +346,22 @@ void PdmlUnknownProtocol::preProtocolHandler(QString name, const QXmlAttributes &attributes, OstProto::Stream *stream) { bool isOk; + int size; int pos = attributes.value("pos").toUInt(&isOk); - Q_ASSERT(isOk); + if (!isOk) + goto _skip_pos_size_proc; - int size = attributes.value("size").toUInt(&isOk); - Q_ASSERT(isOk); + size = attributes.value("size").toUInt(&isOk); + if (!isOk) + goto _skip_pos_size_proc; expPos_ = pos; endPos_ = expPos_ + size; + +_skip_pos_size_proc: + OstProto::HexDump *hexDump = stream->mutable_protocol( + stream->protocol_size()-1)->MutableExtension(OstProto::hexDump); + hexDump->set_pad_until_end(false); } void PdmlUnknownProtocol::postProtocolHandler(OstProto::Stream *stream) @@ -346,7 +369,7 @@ void PdmlUnknownProtocol::postProtocolHandler(OstProto::Stream *stream) OstProto::HexDump *hexDump = stream->mutable_protocol( stream->protocol_size()-1)->MutableExtension(OstProto::hexDump); - // Skipped field? Pad with zero! + // Skipped field(s) at end? Pad with zero! if (endPos_ > expPos_) { QByteArray hexVal(endPos_ - expPos_, char(0)); @@ -355,10 +378,11 @@ void PdmlUnknownProtocol::postProtocolHandler(OstProto::Stream *stream) expPos_ += hexVal.size(); } - Q_ASSERT(expPos_ == endPos_); + qDebug("%s: expPos_ = %d, endPos_ = %d\n", __FUNCTION__, expPos_, endPos_); + //Q_ASSERT(expPos_ == endPos_); hexDump->set_pad_until_end(false); - expPos_ = -1; + endPos_ = expPos_ = -1; } void PdmlUnknownProtocol::unknownFieldHandler(QString name, int pos, int size, @@ -367,11 +391,12 @@ void PdmlUnknownProtocol::unknownFieldHandler(QString name, int pos, int size, OstProto::HexDump *hexDump = stream->mutable_protocol( stream->protocol_size()-1)->MutableExtension(OstProto::hexDump); - qDebug("%s: %s, pos = %d, expPos_ = %d\n", __FUNCTION__, - name.toAscii().constData(), pos, expPos_); + qDebug("%s: %s, pos = %d, expPos_ = %d, endPos_ = %d\n", + __PRETTY_FUNCTION__, name.toAscii().constData(), + pos, expPos_, endPos_); // Skipped field? Pad with zero! - if (pos > expPos_) + if ((pos > expPos_) && (expPos_ < endPos_)) { QByteArray hexVal(pos - expPos_, char(0)); @@ -379,10 +404,11 @@ void PdmlUnknownProtocol::unknownFieldHandler(QString name, int pos, int size, expPos_ += hexVal.size(); } - if (pos == expPos_) + if ((pos == expPos_) /*&& (pos < endPos_)*/) { - QByteArray hexVal = - QByteArray::fromHex(attributes.value("value").toUtf8()); + QByteArray hexVal = attributes.value("unmaskedvalue").isEmpty() ? + QByteArray::fromHex(attributes.value("value").toUtf8()) : + QByteArray::fromHex(attributes.value("unmaskedvalue").toUtf8()); hexDump->mutable_content()->append(hexVal.constData(), hexVal.size()); expPos_ += hexVal.size(); @@ -414,7 +440,59 @@ PdmlFrameProtocol::PdmlFrameProtocol() pdmlProtoName_ = "frame"; } +#if 1 +// ---------------------------------------------------------- // +// PdmlFakeFieldWrapperProtocol // +// ---------------------------------------------------------- // +PdmlFakeFieldWrapperProtocol::PdmlFakeFieldWrapperProtocol() +{ + pdmlProtoName_ = "OST:HexDump"; + ostProtoId_ = OstProto::Protocol::kHexDumpFieldNumber; + + expPos_ = -1; +} + +void PdmlFakeFieldWrapperProtocol::preProtocolHandler(QString name, + const QXmlAttributes &attributes, OstProto::Stream *stream) +{ + expPos_ = 0; + OstProto::HexDump *hexDump = stream->mutable_protocol( + stream->protocol_size()-1)->MutableExtension(OstProto::hexDump); + hexDump->set_pad_until_end(false); +} + +void PdmlFakeFieldWrapperProtocol::postProtocolHandler(OstProto::Stream *stream) +{ + OstProto::HexDump *hexDump = stream->mutable_protocol( + stream->protocol_size()-1)->MutableExtension(OstProto::hexDump); + + qDebug("%s: expPos_ = %d\n", __FUNCTION__, expPos_); + + hexDump->set_pad_until_end(false); + expPos_ = -1; +} + +void PdmlFakeFieldWrapperProtocol::unknownFieldHandler(QString name, int pos, + int size, const QXmlAttributes &attributes, OstProto::Stream *stream) +{ + OstProto::HexDump *hexDump = stream->mutable_protocol( + stream->protocol_size()-1)->MutableExtension(OstProto::hexDump); + + if ((pos == expPos_) && (size >= 0) && + (!attributes.value("unmaskedvalue").isEmpty() || + !attributes.value("value").isEmpty())) + { + QByteArray hexVal = attributes.value("unmaskedvalue").isEmpty() ? + QByteArray::fromHex(attributes.value("value").toUtf8()) : + QByteArray::fromHex(attributes.value("unmaskedvalue").toUtf8()); + + hexDump->mutable_content()->append(hexVal.constData(), hexVal.size()); + expPos_ += hexVal.size(); + } +} + +#endif // ---------------------------------------------------------- // // PdmlEthProtocol // // ---------------------------------------------------------- // @@ -495,3 +573,134 @@ void PdmlIp4Protocol::postProtocolHandler(OstProto::Stream *stream) ip4->set_is_override_cksum(true); // FIXME } +// ---------------------------------------------------------- // +// PdmlIp6Protocol // +// ---------------------------------------------------------- // + +PdmlIp6Protocol::PdmlIp6Protocol() +{ + pdmlProtoName_ = "ipv6"; + ostProtoId_ = OstProto::Protocol::kIp6FieldNumber; + + fieldMap_.insert("ipv6.version", OstProto::Ip6::kVersionFieldNumber); + fieldMap_.insert("ipv6.class", OstProto::Ip6::kTrafficClassFieldNumber); + fieldMap_.insert("ipv6.flow", OstProto::Ip6::kFlowLabelFieldNumber); + fieldMap_.insert("ipv6.plen", OstProto::Ip6::kPayloadLengthFieldNumber); + fieldMap_.insert("ipv6.nxt", OstProto::Ip6::kNextHeaderFieldNumber); + fieldMap_.insert("ipv6.hlim", OstProto::Ip6::kHopLimitFieldNumber); + + // ipv6.src and ipv6.dst handled as unknown fields +} + +void PdmlIp6Protocol::unknownFieldHandler(QString name, int pos, int size, + const QXmlAttributes &attributes, OstProto::Stream *stream) +{ + bool isOk; + + if (name == "ipv6.src") + { + OstProto::Ip6 *ip6 = stream->mutable_protocol( + stream->protocol_size()-1)->MutableExtension(OstProto::ip6); + QString addrHexStr = attributes.value("value"); + + ip6->set_src_addr_hi(addrHexStr.left(16).toULongLong(&isOk, kBaseHex)); + ip6->set_src_addr_lo(addrHexStr.right(16).toULongLong(&isOk, kBaseHex)); + } + else if (name == "ipv6.dst") + { + OstProto::Ip6 *ip6 = stream->mutable_protocol( + stream->protocol_size()-1)->MutableExtension(OstProto::ip6); + QString addrHexStr = attributes.value("value"); + + ip6->set_dst_addr_hi(addrHexStr.left(16).toULongLong(&isOk, kBaseHex)); + ip6->set_dst_addr_lo(addrHexStr.right(16).toULongLong(&isOk, kBaseHex)); + } +} + +void PdmlIp6Protocol::postProtocolHandler(OstProto::Stream *stream) +{ + OstProto::Ip6 *ip6 = stream->mutable_protocol( + stream->protocol_size()-1)->MutableExtension(OstProto::ip6); + + ip6->set_is_override_version(true); // FIXME + ip6->set_is_override_payload_length(true); // FIXME + ip6->set_is_override_next_header(true); // FIXME +} + +// ---------------------------------------------------------- // +// PdmlTcpProtocol // +// ---------------------------------------------------------- // + +PdmlTcpProtocol::PdmlTcpProtocol() +{ + pdmlProtoName_ = "tcp"; + ostProtoId_ = OstProto::Protocol::kTcpFieldNumber; + + fieldMap_.insert("tcp.srcport", OstProto::Tcp::kSrcPortFieldNumber); + fieldMap_.insert("tcp.dstport", OstProto::Tcp::kDstPortFieldNumber); + fieldMap_.insert("tcp.seq", OstProto::Tcp::kSeqNumFieldNumber); + fieldMap_.insert("tcp.ack", OstProto::Tcp::kAckNumFieldNumber); + fieldMap_.insert("tcp.hdr_len", OstProto::Tcp::kHdrlenRsvdFieldNumber); + fieldMap_.insert("tcp.flags", OstProto::Tcp::kFlagsFieldNumber); + fieldMap_.insert("tcp.window_size", OstProto::Tcp::kWindowFieldNumber); + fieldMap_.insert("tcp.checksum", OstProto::Tcp::kCksumFieldNumber); + fieldMap_.insert("tcp.urgent_pointer", OstProto::Tcp::kUrgPtrFieldNumber); +} + +void PdmlTcpProtocol::unknownFieldHandler(QString name, int pos, int size, + const QXmlAttributes &attributes, OstProto::Stream *stream) +{ + if (name == "tcp.options") + options_ = QByteArray::fromHex(attributes.value("value").toUtf8()); + else if (name == "" + && attributes.value("show").startsWith("TCP segment data")) + { + segmentData_ = QByteArray::fromHex(attributes.value("value").toUtf8()); + stream->mutable_core()->mutable_name()->append(segmentData_.constData(), + segmentData_.size()); + } +} + +void PdmlTcpProtocol::postProtocolHandler(OstProto::Stream *stream) +{ + OstProto::Tcp *tcp = stream->mutable_protocol( + stream->protocol_size()-1)->MutableExtension(OstProto::tcp); + + tcp->set_is_override_src_port(true); // FIXME + tcp->set_is_override_dst_port(true); // FIXME + tcp->set_is_override_hdrlen(true); // FIXME + tcp->set_is_override_cksum(true); // FIXME + + if (options_.size()) + { + OstProto::Protocol *proto = stream->add_protocol(); + + proto->mutable_protocol_id()->set_id( + OstProto::Protocol::kHexDumpFieldNumber); + + OstProto::HexDump *hexDump = proto->MutableExtension(OstProto::hexDump); + + hexDump->mutable_content()->append(options_.constData(), + options_.size()); + hexDump->set_pad_until_end(false); + options_.resize(0); + } + +#if 0 + if (segmentData_.size()) + { + OstProto::Protocol *proto = stream->add_protocol(); + + proto->mutable_protocol_id()->set_id( + OstProto::Protocol::kHexDumpFieldNumber); + + OstProto::HexDump *hexDump = proto->MutableExtension(OstProto::hexDump); + + hexDump->mutable_content()->append(segmentData_.constData(), + segmentData_.size()); + hexDump->set_pad_until_end(false); + segmentData_.resize(0); + } +#endif +} + diff --git a/common/pdml_p.h b/common/pdml_p.h index bfa7a01..e125dd6 100644 --- a/common/pdml_p.h +++ b/common/pdml_p.h @@ -21,11 +21,14 @@ along with this program. If not, see #include "protocol.pb.h" +#include #include #include #include #include +// TODO: add const where possible + class QXmlSimpleReader; class QXmlInputSource; @@ -73,7 +76,6 @@ private: QMap protocolMap_; PdmlDefaultProtocol *currentPdmlProtocol_; - bool skipUntilEndOfPacket_; int skipCount_; int packetCount_; OstProto::StreamConfigList *streams_; @@ -112,6 +114,22 @@ public: PdmlFrameProtocol(); }; +#if 1 +class PdmlFakeFieldWrapperProtocol : public PdmlDefaultProtocol +{ +public: + PdmlFakeFieldWrapperProtocol(); + + virtual void preProtocolHandler(QString name, + const QXmlAttributes &attributes, OstProto::Stream *stream); + virtual void postProtocolHandler(OstProto::Stream *stream); + virtual void unknownFieldHandler(QString name, int pos, int size, + const QXmlAttributes &attributes, OstProto::Stream *stream); +private: + int expPos_; +}; +#endif + class PdmlEthProtocol : public PdmlDefaultProtocol { public: @@ -129,4 +147,26 @@ public: const QXmlAttributes &attributes, OstProto::Stream *stream); virtual void postProtocolHandler(OstProto::Stream *stream); }; + +class PdmlIp6Protocol : public PdmlDefaultProtocol +{ +public: + PdmlIp6Protocol(); + virtual void unknownFieldHandler(QString name, int pos, int size, + const QXmlAttributes &attributes, OstProto::Stream *stream); + virtual void postProtocolHandler(OstProto::Stream *stream); +}; + +class PdmlTcpProtocol : public PdmlDefaultProtocol +{ +public: + PdmlTcpProtocol(); + virtual void unknownFieldHandler(QString name, int pos, int size, + const QXmlAttributes &attributes, OstProto::Stream *stream); + virtual void postProtocolHandler(OstProto::Stream *stream); +private: + QByteArray options_; + QByteArray segmentData_; +}; + #endif diff --git a/server/pcapport.cpp b/server/pcapport.cpp index d4d1223..0c283c0 100644 --- a/server/pcapport.cpp +++ b/server/pcapport.cpp @@ -311,7 +311,7 @@ void PcapPort::PortTransmitter::run() // 'stats callback' function so that both Rx and Tx stats are updated // together - const int kSyncTransmit = 1; + const int kSyncTransmit = 0; // temp mask, shd be 1; int i; qDebug("sendQueueList_.size = %d", sendQueueList_.size());