2015-04-16 11:50:07 -05:00
|
|
|
/*
|
|
|
|
Copyright (C) 2010 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 <http://www.gnu.org/licenses/>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ip6.h"
|
2020-03-27 10:44:13 -05:00
|
|
|
|
|
|
|
#include "uint128.h"
|
2015-04-16 11:50:07 -05:00
|
|
|
#include <QHostAddress>
|
|
|
|
|
|
|
|
|
|
|
|
Ip6Protocol::Ip6Protocol(StreamBase *stream, AbstractProtocol *parent)
|
|
|
|
: AbstractProtocol(stream, parent)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Ip6Protocol::~Ip6Protocol()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
AbstractProtocol* Ip6Protocol::createInstance(StreamBase *stream,
|
|
|
|
AbstractProtocol *parent)
|
|
|
|
{
|
|
|
|
return new Ip6Protocol(stream, parent);
|
|
|
|
}
|
|
|
|
|
|
|
|
quint32 Ip6Protocol::protocolNumber() const
|
|
|
|
{
|
|
|
|
return OstProto::Protocol::kIp6FieldNumber;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Ip6Protocol::protoDataCopyInto(OstProto::Protocol &protocol) const
|
|
|
|
{
|
|
|
|
protocol.MutableExtension(OstProto::ip6)->CopyFrom(data);
|
|
|
|
protocol.mutable_protocol_id()->set_id(protocolNumber());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Ip6Protocol::protoDataCopyFrom(const OstProto::Protocol &protocol)
|
|
|
|
{
|
|
|
|
if (protocol.protocol_id().id() == protocolNumber() &&
|
|
|
|
protocol.HasExtension(OstProto::ip6))
|
|
|
|
data.MergeFrom(protocol.GetExtension(OstProto::ip6));
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Ip6Protocol::name() const
|
|
|
|
{
|
|
|
|
return QString("Internet Protocol ver 6");
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Ip6Protocol::shortName() const
|
|
|
|
{
|
|
|
|
return QString("IPv6");
|
|
|
|
}
|
|
|
|
|
|
|
|
AbstractProtocol::ProtocolIdType Ip6Protocol::protocolIdType() const
|
|
|
|
{
|
|
|
|
return ProtocolIdIp;
|
|
|
|
}
|
|
|
|
|
|
|
|
quint32 Ip6Protocol::protocolId(ProtocolIdType type) const
|
|
|
|
{
|
|
|
|
switch(type)
|
|
|
|
{
|
|
|
|
case ProtocolIdEth: return 0x86dd;
|
|
|
|
case ProtocolIdIp: return 0x29;
|
|
|
|
default:break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return AbstractProtocol::protocolId(type);
|
|
|
|
}
|
|
|
|
|
|
|
|
int Ip6Protocol::fieldCount() const
|
|
|
|
{
|
|
|
|
return ip6_fieldCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
AbstractProtocol::FieldFlags Ip6Protocol::fieldFlags(int index) const
|
|
|
|
{
|
|
|
|
AbstractProtocol::FieldFlags flags;
|
|
|
|
|
|
|
|
flags = AbstractProtocol::fieldFlags(index);
|
|
|
|
|
|
|
|
switch (index)
|
|
|
|
{
|
|
|
|
case ip6_version:
|
|
|
|
case ip6_trafficClass:
|
|
|
|
case ip6_flowLabel:
|
|
|
|
case ip6_payloadLength:
|
|
|
|
case ip6_nextHeader:
|
|
|
|
case ip6_hopLimit:
|
|
|
|
case ip6_srcAddress:
|
|
|
|
case ip6_dstAddress:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ip6_isOverrideVersion:
|
|
|
|
case ip6_isOverridePayloadLength:
|
|
|
|
case ip6_isOverrideNextHeader:
|
|
|
|
|
|
|
|
case ip6_srcAddrMode:
|
|
|
|
case ip6_srcAddrCount:
|
|
|
|
case ip6_srcAddrPrefix:
|
|
|
|
|
|
|
|
case ip6_dstAddrMode:
|
|
|
|
case ip6_dstAddrCount:
|
|
|
|
case ip6_dstAddrPrefix:
|
|
|
|
flags &= ~FrameField;
|
|
|
|
flags |= MetaField;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
qFatal("%s: unimplemented case %d in switch", __PRETTY_FUNCTION__,
|
|
|
|
index);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant Ip6Protocol::fieldData(int index, FieldAttrib attrib,
|
|
|
|
int streamIndex) const
|
|
|
|
{
|
|
|
|
switch (index)
|
|
|
|
{
|
|
|
|
case ip6_version:
|
|
|
|
{
|
|
|
|
quint8 ver;
|
|
|
|
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue:
|
|
|
|
case FieldFrameValue:
|
|
|
|
case FieldTextValue:
|
|
|
|
if (data.is_override_version())
|
|
|
|
ver = data.version() & 0xF;
|
|
|
|
else
|
|
|
|
ver = 0x6;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ver = 0; // avoid the 'maybe used unitialized' warning
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Version");
|
|
|
|
case FieldValue:
|
|
|
|
return ver;
|
|
|
|
case FieldTextValue:
|
|
|
|
return QString("%1").arg(ver);
|
|
|
|
case FieldFrameValue:
|
|
|
|
return QByteArray(1, char(ver));
|
|
|
|
case FieldBitSize:
|
|
|
|
return 4;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_trafficClass:
|
|
|
|
{
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Traffic Class");
|
|
|
|
case FieldValue:
|
|
|
|
return data.traffic_class() & 0xFF;
|
|
|
|
case FieldTextValue:
|
|
|
|
return QString("%1").arg(data.traffic_class() & 0xFF,
|
|
|
|
2, BASE_HEX, QChar('0'));
|
|
|
|
case FieldFrameValue:
|
|
|
|
return QByteArray(1, char(data.traffic_class() & 0xFF));
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_flowLabel:
|
|
|
|
{
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Flow Label");
|
|
|
|
case FieldValue:
|
|
|
|
return data.flow_label() & 0xFFFFF;
|
|
|
|
case FieldTextValue:
|
|
|
|
return QString("%1").arg(data.flow_label() & 0xFFFFF,
|
|
|
|
5, BASE_HEX, QChar('0'));
|
|
|
|
case FieldFrameValue:
|
|
|
|
{
|
|
|
|
QByteArray fv;
|
|
|
|
fv.resize(4);
|
|
|
|
qToBigEndian((quint32) data.flow_label() & 0xFFFFF,
|
|
|
|
(uchar*) fv.data());
|
|
|
|
fv = fv.right(3);
|
|
|
|
return fv;
|
|
|
|
}
|
|
|
|
case FieldBitSize:
|
|
|
|
return 20;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_payloadLength:
|
|
|
|
{
|
|
|
|
quint16 len;
|
|
|
|
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue:
|
|
|
|
case FieldFrameValue:
|
|
|
|
case FieldTextValue:
|
|
|
|
if (data.is_override_payload_length())
|
|
|
|
len = data.payload_length();
|
|
|
|
else
|
|
|
|
len = protocolFramePayloadSize(streamIndex);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
len = 0; // avoid the 'maybe used unitialized' warning
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Payload Length");
|
|
|
|
case FieldValue:
|
|
|
|
return len;
|
|
|
|
case FieldFrameValue:
|
|
|
|
{
|
|
|
|
QByteArray fv;
|
|
|
|
fv.resize(2);
|
|
|
|
qToBigEndian(len, (uchar*) fv.data());
|
|
|
|
return fv;
|
|
|
|
}
|
|
|
|
case FieldTextValue:
|
|
|
|
return QString("%1").arg(len);
|
|
|
|
case FieldBitSize:
|
|
|
|
return 16;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_nextHeader:
|
|
|
|
{
|
|
|
|
quint8 nextHdr;
|
|
|
|
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue:
|
|
|
|
case FieldFrameValue:
|
|
|
|
case FieldTextValue:
|
|
|
|
if (data.is_override_next_header()) {
|
|
|
|
nextHdr = data.next_header();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nextHdr = payloadProtocolId(ProtocolIdIp);
|
|
|
|
if ((nextHdr == 0)
|
|
|
|
&& next
|
|
|
|
&& (next->protocolIdType() == ProtocolIdNone)) {
|
|
|
|
nextHdr = 0x3b; // IPv6 No-Next-Header
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
nextHdr = 0; // avoid the 'maybe used unitialized' warning
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Next Header");
|
|
|
|
case FieldValue:
|
|
|
|
return nextHdr;
|
|
|
|
case FieldTextValue:
|
|
|
|
return QString("%1").arg(nextHdr, 2, BASE_HEX, QChar('0'));
|
|
|
|
case FieldFrameValue:
|
|
|
|
return QByteArray(1, char(nextHdr));
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_hopLimit:
|
|
|
|
{
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Hop Limit");
|
|
|
|
case FieldValue:
|
|
|
|
return data.hop_limit() & 0xFF;
|
|
|
|
case FieldTextValue:
|
|
|
|
return QString("%1").arg(data.hop_limit() & 0xFF);
|
|
|
|
case FieldFrameValue:
|
|
|
|
return QByteArray(1, char(data.hop_limit() & 0xFF));
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case ip6_srcAddress:
|
|
|
|
{
|
2020-03-27 10:44:13 -05:00
|
|
|
int u;
|
|
|
|
UInt128 mask = 0;
|
|
|
|
UInt128 prefix = 0;
|
|
|
|
UInt128 host = 0;
|
|
|
|
UInt128 src(data.src_addr_hi(), data.src_addr_lo());
|
2015-04-16 11:50:07 -05:00
|
|
|
|
|
|
|
switch(data.src_addr_mode())
|
|
|
|
{
|
|
|
|
case OstProto::Ip6::kFixed:
|
|
|
|
break;
|
|
|
|
case OstProto::Ip6::kIncHost:
|
|
|
|
case OstProto::Ip6::kDecHost:
|
|
|
|
case OstProto::Ip6::kRandomHost:
|
|
|
|
u = streamIndex % data.src_addr_count();
|
2020-03-27 10:44:13 -05:00
|
|
|
mask = ~UInt128(0, 0) << (128 - data.src_addr_prefix());
|
|
|
|
prefix = src & mask;
|
2015-04-16 11:50:07 -05:00
|
|
|
if (data.src_addr_mode() == OstProto::Ip6::kIncHost) {
|
2020-03-27 10:44:13 -05:00
|
|
|
host = ((src & ~mask) + u) & ~mask;
|
2015-04-16 11:50:07 -05:00
|
|
|
}
|
|
|
|
else if (data.src_addr_mode() == OstProto::Ip6::kDecHost) {
|
2020-03-27 10:44:13 -05:00
|
|
|
host = ((src & ~mask) - u) & ~mask;
|
2015-04-16 11:50:07 -05:00
|
|
|
}
|
|
|
|
else if (data.src_addr_mode()==OstProto::Ip6::kRandomHost) {
|
2020-03-27 10:44:13 -05:00
|
|
|
// XXX: qrand is int (32bit) not 64bit, some stdlib
|
|
|
|
// implementations have RAND_MAX as low as 0x7FFF
|
|
|
|
host = UInt128(qrand(), qrand()) & ~mask;
|
2015-04-16 11:50:07 -05:00
|
|
|
}
|
2020-03-27 10:44:13 -05:00
|
|
|
src = prefix | host;
|
2015-04-16 11:50:07 -05:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
qWarning("Unhandled src_addr_mode = %d",
|
|
|
|
data.src_addr_mode());
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Source");
|
|
|
|
case FieldValue:
|
|
|
|
case FieldFrameValue:
|
|
|
|
case FieldTextValue:
|
|
|
|
{
|
|
|
|
QByteArray fv;
|
|
|
|
fv.resize(16);
|
2020-03-27 10:44:13 -05:00
|
|
|
qToBigEndian(src, (uchar*) fv.data());
|
2015-04-16 11:50:07 -05:00
|
|
|
if (attrib == FieldTextValue)
|
2020-03-27 10:44:13 -05:00
|
|
|
return QHostAddress(src.toArray()).toString();
|
2015-04-16 11:50:07 -05:00
|
|
|
else
|
|
|
|
return fv;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case ip6_dstAddress:
|
|
|
|
{
|
2020-03-27 10:44:13 -05:00
|
|
|
int u;
|
|
|
|
UInt128 mask = 0;
|
|
|
|
UInt128 prefix = 0;
|
|
|
|
UInt128 host = 0;
|
|
|
|
UInt128 dst(data.dst_addr_hi(), data.dst_addr_lo());
|
2015-04-16 11:50:07 -05:00
|
|
|
|
|
|
|
switch(data.dst_addr_mode())
|
|
|
|
{
|
|
|
|
case OstProto::Ip6::kFixed:
|
|
|
|
break;
|
|
|
|
case OstProto::Ip6::kIncHost:
|
|
|
|
case OstProto::Ip6::kDecHost:
|
|
|
|
case OstProto::Ip6::kRandomHost:
|
|
|
|
u = streamIndex % data.dst_addr_count();
|
2020-03-27 10:44:13 -05:00
|
|
|
mask = ~UInt128(0, 0) << (128 - data.dst_addr_prefix());
|
|
|
|
prefix = dst & mask;
|
2015-04-16 11:50:07 -05:00
|
|
|
if (data.dst_addr_mode() == OstProto::Ip6::kIncHost) {
|
2020-03-27 10:44:13 -05:00
|
|
|
host = ((dst & ~mask) + u) & ~mask;
|
2015-04-16 11:50:07 -05:00
|
|
|
}
|
|
|
|
else if (data.dst_addr_mode() == OstProto::Ip6::kDecHost) {
|
2020-03-27 10:44:13 -05:00
|
|
|
host = ((dst & ~mask) - u) & ~mask;
|
2015-04-16 11:50:07 -05:00
|
|
|
}
|
|
|
|
else if (data.dst_addr_mode()==OstProto::Ip6::kRandomHost) {
|
2020-03-27 10:44:13 -05:00
|
|
|
// XXX: qrand is int (32bit) not 64bit, some stdlib
|
|
|
|
// implementations have RAND_MAX as low as 0x7FFF
|
|
|
|
host = UInt128(qrand(), qrand()) & ~mask;
|
2015-04-16 11:50:07 -05:00
|
|
|
}
|
2020-03-27 10:44:13 -05:00
|
|
|
dst = prefix | host;
|
2015-04-16 11:50:07 -05:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
qWarning("Unhandled dst_addr_mode = %d",
|
|
|
|
data.dst_addr_mode());
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Destination");
|
|
|
|
case FieldValue:
|
|
|
|
case FieldFrameValue:
|
|
|
|
case FieldTextValue:
|
|
|
|
{
|
|
|
|
QByteArray fv;
|
|
|
|
fv.resize(16);
|
2020-03-27 10:44:13 -05:00
|
|
|
qToBigEndian(dst, (uchar*) fv.data());
|
2015-04-16 11:50:07 -05:00
|
|
|
if (attrib == FieldTextValue)
|
2020-03-27 10:44:13 -05:00
|
|
|
return QHostAddress(dst.toArray()).toString();
|
2015-04-16 11:50:07 -05:00
|
|
|
else
|
|
|
|
return fv;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Meta-Fields
|
|
|
|
case ip6_isOverrideVersion:
|
|
|
|
{
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue:
|
|
|
|
return data.is_override_version();
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_isOverridePayloadLength:
|
|
|
|
{
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue:
|
|
|
|
return data.is_override_payload_length();
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_isOverrideNextHeader:
|
|
|
|
{
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue:
|
|
|
|
return data.is_override_next_header();
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case ip6_srcAddrMode:
|
|
|
|
{
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue:
|
|
|
|
return data.src_addr_mode();
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_srcAddrCount:
|
|
|
|
{
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue:
|
|
|
|
return data.src_addr_count();
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_srcAddrPrefix:
|
|
|
|
{
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue:
|
|
|
|
return data.src_addr_prefix();
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case ip6_dstAddrMode:
|
|
|
|
{
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue:
|
|
|
|
return data.dst_addr_mode();
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_dstAddrCount:
|
|
|
|
{
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue:
|
|
|
|
return data.dst_addr_count();
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_dstAddrPrefix:
|
|
|
|
{
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue:
|
|
|
|
return data.dst_addr_prefix();
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
qFatal("%s: unimplemented case %d in switch", __PRETTY_FUNCTION__,
|
|
|
|
index);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return AbstractProtocol::fieldData(index, attrib, streamIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Ip6Protocol::setFieldData(int index, const QVariant &value,
|
|
|
|
FieldAttrib attrib)
|
|
|
|
{
|
|
|
|
bool isOk = false;
|
|
|
|
|
|
|
|
if (attrib != FieldValue)
|
|
|
|
goto _exit;
|
|
|
|
|
|
|
|
switch (index)
|
|
|
|
{
|
|
|
|
case ip6_version:
|
|
|
|
{
|
|
|
|
uint ver = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_version(ver & 0xF);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_trafficClass:
|
|
|
|
{
|
|
|
|
uint trfClass = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_traffic_class(trfClass & 0xFF);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_flowLabel:
|
|
|
|
{
|
|
|
|
uint fl = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_flow_label(fl & 0xFFFFF);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_payloadLength:
|
|
|
|
{
|
|
|
|
uint len = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_payload_length(len & 0xFFFF);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_nextHeader:
|
|
|
|
{
|
|
|
|
uint ver = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_next_header(ver & 0xFF);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_hopLimit:
|
|
|
|
{
|
|
|
|
uint hl = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_hop_limit(hl & 0xFF);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_srcAddress:
|
|
|
|
{
|
|
|
|
Q_IPV6ADDR addr = QHostAddress(value.toString()).toIPv6Address();
|
|
|
|
quint64 x;
|
|
|
|
|
|
|
|
x = (quint64(addr[0]) << 56)
|
|
|
|
| (quint64(addr[1]) << 48)
|
|
|
|
| (quint64(addr[2]) << 40)
|
|
|
|
| (quint64(addr[3]) << 32)
|
|
|
|
| (quint64(addr[4]) << 24)
|
|
|
|
| (quint64(addr[5]) << 16)
|
|
|
|
| (quint64(addr[6]) << 8)
|
|
|
|
| (quint64(addr[7]) << 0);
|
|
|
|
data.set_src_addr_hi(x);
|
|
|
|
|
|
|
|
x = (quint64(addr[ 8]) << 56)
|
|
|
|
| (quint64(addr[ 9]) << 48)
|
|
|
|
| (quint64(addr[10]) << 40)
|
|
|
|
| (quint64(addr[11]) << 32)
|
|
|
|
| (quint64(addr[12]) << 24)
|
|
|
|
| (quint64(addr[13]) << 16)
|
|
|
|
| (quint64(addr[14]) << 8)
|
|
|
|
| (quint64(addr[15]) << 0);
|
|
|
|
data.set_src_addr_lo(x);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_dstAddress:
|
|
|
|
{
|
|
|
|
Q_IPV6ADDR addr = QHostAddress(value.toString()).toIPv6Address();
|
|
|
|
quint64 x;
|
|
|
|
|
|
|
|
x = (quint64(addr[0]) << 56)
|
|
|
|
| (quint64(addr[1]) << 48)
|
|
|
|
| (quint64(addr[2]) << 40)
|
|
|
|
| (quint64(addr[3]) << 32)
|
|
|
|
| (quint64(addr[4]) << 24)
|
|
|
|
| (quint64(addr[5]) << 16)
|
|
|
|
| (quint64(addr[6]) << 8)
|
|
|
|
| (quint64(addr[7]) << 0);
|
|
|
|
data.set_dst_addr_hi(x);
|
|
|
|
|
|
|
|
x = (quint64(addr[ 8]) << 56)
|
|
|
|
| (quint64(addr[ 9]) << 48)
|
|
|
|
| (quint64(addr[10]) << 40)
|
|
|
|
| (quint64(addr[11]) << 32)
|
|
|
|
| (quint64(addr[12]) << 24)
|
|
|
|
| (quint64(addr[13]) << 16)
|
|
|
|
| (quint64(addr[14]) << 8)
|
|
|
|
| (quint64(addr[15]) << 0);
|
|
|
|
data.set_dst_addr_lo(x);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Meta-Fields
|
|
|
|
case ip6_isOverrideVersion:
|
|
|
|
{
|
|
|
|
bool ovr = value.toBool();
|
|
|
|
data.set_is_override_version(ovr);
|
|
|
|
isOk = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_isOverridePayloadLength:
|
|
|
|
{
|
|
|
|
bool ovr = value.toBool();
|
|
|
|
data.set_is_override_payload_length(ovr);
|
|
|
|
isOk = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_isOverrideNextHeader:
|
|
|
|
{
|
|
|
|
bool ovr = value.toBool();
|
|
|
|
data.set_is_override_next_header(ovr);
|
|
|
|
isOk = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case ip6_srcAddrMode:
|
|
|
|
{
|
|
|
|
uint mode = value.toUInt(&isOk);
|
|
|
|
if (isOk && data.AddrMode_IsValid(mode))
|
|
|
|
data.set_src_addr_mode((OstProto::Ip6::AddrMode) mode);
|
|
|
|
else
|
|
|
|
isOk = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_srcAddrCount:
|
|
|
|
{
|
|
|
|
uint count = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_src_addr_count(count);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_srcAddrPrefix:
|
|
|
|
{
|
|
|
|
uint prefix = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_src_addr_prefix(prefix);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case ip6_dstAddrMode:
|
|
|
|
{
|
|
|
|
uint mode = value.toUInt(&isOk);
|
|
|
|
if (isOk && data.AddrMode_IsValid(mode))
|
|
|
|
data.set_dst_addr_mode((OstProto::Ip6::AddrMode) mode);
|
|
|
|
else
|
|
|
|
isOk = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_dstAddrCount:
|
|
|
|
{
|
|
|
|
uint count = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_dst_addr_count(count);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip6_dstAddrPrefix:
|
|
|
|
{
|
|
|
|
uint prefix = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_dst_addr_prefix(prefix);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
qFatal("%s: unimplemented case %d in switch", __PRETTY_FUNCTION__,
|
|
|
|
index);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
_exit:
|
|
|
|
return isOk;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Ip6Protocol::protocolFrameVariableCount() const
|
|
|
|
{
|
2015-05-27 10:06:49 -05:00
|
|
|
int count = AbstractProtocol::protocolFrameVariableCount();
|
2015-04-16 11:50:07 -05:00
|
|
|
|
|
|
|
if (data.src_addr_mode() != OstProto::Ip6::kFixed)
|
|
|
|
count = AbstractProtocol::lcm(count, data.src_addr_count());
|
|
|
|
|
|
|
|
if (data.dst_addr_mode() != OstProto::Ip6::kFixed)
|
|
|
|
count = AbstractProtocol::lcm(count, data.dst_addr_count());
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
quint32 Ip6Protocol::protocolFrameCksum(int streamIndex,
|
2021-09-04 07:46:40 -05:00
|
|
|
CksumType cksumType, CksumFlags cksumFlags) const
|
2015-04-16 11:50:07 -05:00
|
|
|
{
|
|
|
|
if (cksumType == CksumIpPseudo)
|
|
|
|
{
|
|
|
|
quint32 sum = 0;
|
2015-05-26 11:13:37 -05:00
|
|
|
QByteArray fv = protocolFrameValue(streamIndex);
|
2015-06-06 04:58:16 -05:00
|
|
|
const quint8 *p = (quint8*) fv.constData();
|
2015-04-16 11:50:07 -05:00
|
|
|
|
2015-05-26 11:13:37 -05:00
|
|
|
// src-ip, dst-ip
|
|
|
|
for (int i = 8; i < fv.size(); i+=2)
|
|
|
|
sum += *((quint16*)(p + i));
|
2018-09-13 02:02:36 -05:00
|
|
|
|
|
|
|
// XXX: payload length and protocol are also part of the
|
|
|
|
// pseudo cksum but we need to skip extension headers to
|
|
|
|
// get to them as per RFC 8200 Section 8.1
|
|
|
|
// Since we can't traverse beyond our immediate neighboring
|
|
|
|
// protocol from here, these two fields are counted in the
|
|
|
|
// pseudo cksum in AbstractProtocol::protocolFrameHeaderCksum()
|
2015-04-16 11:50:07 -05:00
|
|
|
|
|
|
|
while(sum>>16)
|
|
|
|
sum = (sum & 0xFFFF) + (sum >> 16);
|
|
|
|
|
2018-09-13 02:02:36 -05:00
|
|
|
return qFromBigEndian((quint16) ~sum);
|
2015-04-16 11:50:07 -05:00
|
|
|
}
|
2021-09-04 07:46:40 -05:00
|
|
|
return AbstractProtocol::protocolFrameCksum(
|
|
|
|
streamIndex, cksumType, cksumFlags);
|
2015-04-16 11:50:07 -05:00
|
|
|
}
|
|
|
|
|
2019-06-05 01:09:09 -05:00
|
|
|
bool Ip6Protocol::hasErrors(QStringList *errors) const
|
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
|
|
|
|
if ((data.dst_addr_hi() == 0ULL) && (data.dst_addr_lo() == 0ULL)
|
|
|
|
&& (data.dst_addr_mode() == OstProto::Ip6::kFixed)) {
|
|
|
|
if (errors)
|
|
|
|
*errors << QObject::tr("Frames with Destination IP :: (all zeroes) "
|
|
|
|
"are likely to be dropped");
|
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((data.src_addr_hi() == 0ULL) && (data.src_addr_lo() == 0ULL)
|
|
|
|
&& (data.src_addr_mode() == OstProto::Ip6::kFixed)) {
|
|
|
|
if (errors)
|
|
|
|
*errors << QObject::tr("Frames with Source IP :: (all zeroes) "
|
|
|
|
"are likely to be dropped");
|
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|