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 "ip4.h"
|
|
|
|
|
|
|
|
#include <QHostAddress>
|
|
|
|
|
|
|
|
Ip4Protocol::Ip4Protocol(StreamBase *stream, AbstractProtocol *parent)
|
|
|
|
: AbstractProtocol(stream, parent)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Ip4Protocol::~Ip4Protocol()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
AbstractProtocol* Ip4Protocol::createInstance(StreamBase *stream,
|
|
|
|
AbstractProtocol *parent)
|
|
|
|
{
|
|
|
|
return new Ip4Protocol(stream, parent);
|
|
|
|
}
|
|
|
|
|
|
|
|
quint32 Ip4Protocol::protocolNumber() const
|
|
|
|
{
|
|
|
|
return OstProto::Protocol::kIp4FieldNumber;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Ip4Protocol::protoDataCopyInto(OstProto::Protocol &protocol) const
|
|
|
|
{
|
|
|
|
protocol.MutableExtension(OstProto::ip4)->CopyFrom(data);
|
|
|
|
protocol.mutable_protocol_id()->set_id(protocolNumber());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Ip4Protocol::protoDataCopyFrom(const OstProto::Protocol &protocol)
|
|
|
|
{
|
|
|
|
if (protocol.protocol_id().id() == protocolNumber() &&
|
|
|
|
protocol.HasExtension(OstProto::ip4))
|
|
|
|
data.MergeFrom(protocol.GetExtension(OstProto::ip4));
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Ip4Protocol::name() const
|
|
|
|
{
|
|
|
|
return QString("Internet Protocol ver 4");
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Ip4Protocol::shortName() const
|
|
|
|
{
|
|
|
|
return QString("IPv4");
|
|
|
|
}
|
|
|
|
|
|
|
|
AbstractProtocol::ProtocolIdType Ip4Protocol::protocolIdType() const
|
|
|
|
{
|
|
|
|
return ProtocolIdIp;
|
|
|
|
}
|
|
|
|
|
|
|
|
quint32 Ip4Protocol::protocolId(ProtocolIdType type) const
|
|
|
|
{
|
|
|
|
switch(type)
|
|
|
|
{
|
|
|
|
case ProtocolIdLlc: return 0x060603;
|
|
|
|
case ProtocolIdEth: return 0x0800;
|
|
|
|
case ProtocolIdIp: return 0x04;
|
|
|
|
default:break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return AbstractProtocol::protocolId(type);
|
|
|
|
}
|
|
|
|
|
|
|
|
int Ip4Protocol::fieldCount() const
|
|
|
|
{
|
|
|
|
return ip4_fieldCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
AbstractProtocol::FieldFlags Ip4Protocol::fieldFlags(int index) const
|
|
|
|
{
|
|
|
|
AbstractProtocol::FieldFlags flags;
|
|
|
|
|
|
|
|
flags = AbstractProtocol::fieldFlags(index);
|
|
|
|
|
|
|
|
switch (index)
|
|
|
|
{
|
|
|
|
case ip4_ver:
|
|
|
|
case ip4_hdrLen:
|
|
|
|
case ip4_tos:
|
|
|
|
case ip4_totLen:
|
|
|
|
case ip4_id:
|
|
|
|
case ip4_flags:
|
|
|
|
case ip4_fragOfs:
|
|
|
|
case ip4_ttl:
|
|
|
|
case ip4_proto:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ip4_cksum:
|
|
|
|
flags |= CksumField;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ip4_srcAddr:
|
|
|
|
case ip4_dstAddr:
|
2016-10-27 13:20:24 -05:00
|
|
|
case ip4_options:
|
2015-04-16 11:50:07 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ip4_isOverrideVer:
|
|
|
|
case ip4_isOverrideHdrLen:
|
|
|
|
case ip4_isOverrideTotLen:
|
|
|
|
case ip4_isOverrideProto:
|
|
|
|
case ip4_isOverrideCksum:
|
|
|
|
case ip4_srcAddrMode:
|
|
|
|
case ip4_srcAddrCount:
|
|
|
|
case ip4_srcAddrMask:
|
|
|
|
case ip4_dstAddrMode:
|
|
|
|
case ip4_dstAddrCount:
|
|
|
|
case ip4_dstAddrMask:
|
|
|
|
flags &= ~FrameField;
|
|
|
|
flags |= MetaField;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant Ip4Protocol::fieldData(int index, FieldAttrib attrib,
|
|
|
|
int streamIndex) const
|
|
|
|
{
|
|
|
|
switch (index)
|
|
|
|
{
|
|
|
|
case ip4_ver:
|
|
|
|
{
|
|
|
|
int ver;
|
|
|
|
|
|
|
|
ver = data.is_override_ver() ? (data.ver_hdrlen() >> 4) & 0x0F : 4;
|
|
|
|
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Version");
|
|
|
|
case FieldValue:
|
|
|
|
return ver;
|
|
|
|
case FieldTextValue:
|
|
|
|
return QString("%1").arg(ver, 1, BASE_HEX, QChar('0'));
|
|
|
|
case FieldFrameValue:
|
|
|
|
return QByteArray(1, (char) ver);
|
|
|
|
case FieldBitSize:
|
|
|
|
return 4;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_hdrLen:
|
|
|
|
{
|
|
|
|
int hdrlen;
|
|
|
|
|
2016-10-27 13:20:24 -05:00
|
|
|
hdrlen = data.is_override_hdrlen() ?
|
|
|
|
data.ver_hdrlen() : 5 + data.options().length()/4;
|
|
|
|
hdrlen &= 0x0F;
|
2015-04-16 11:50:07 -05:00
|
|
|
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Header Length");
|
|
|
|
case FieldValue:
|
|
|
|
return hdrlen;
|
|
|
|
case FieldTextValue:
|
|
|
|
return QString("%1").arg(hdrlen, 1, BASE_HEX, QChar('0'));
|
|
|
|
case FieldFrameValue:
|
|
|
|
return QByteArray(1, (char) hdrlen);
|
|
|
|
case FieldBitSize:
|
|
|
|
return 4;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_tos:
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("TOS/DSCP");
|
|
|
|
case FieldValue:
|
|
|
|
return data.tos();
|
|
|
|
case FieldFrameValue:
|
|
|
|
return QByteArray(1, (char) data.tos());
|
|
|
|
case FieldTextValue:
|
|
|
|
return QString("0x%1").
|
|
|
|
arg(data.tos(), 2, BASE_HEX, QChar('0'));;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ip4_totLen:
|
|
|
|
{
|
2016-10-27 13:20:24 -05:00
|
|
|
int ipLen = 20 + data.options().length();
|
2015-04-16 11:50:07 -05:00
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Total Length");
|
|
|
|
case FieldValue:
|
|
|
|
{
|
|
|
|
int totlen;
|
|
|
|
totlen = data.is_override_totlen() ? data.totlen() :
|
2016-10-27 13:20:24 -05:00
|
|
|
(protocolFramePayloadSize(streamIndex) + ipLen);
|
2015-04-16 11:50:07 -05:00
|
|
|
return totlen;
|
|
|
|
}
|
|
|
|
case FieldFrameValue:
|
|
|
|
{
|
|
|
|
QByteArray fv;
|
|
|
|
int totlen;
|
|
|
|
totlen = data.is_override_totlen() ? data.totlen() :
|
2016-10-27 13:20:24 -05:00
|
|
|
(protocolFramePayloadSize(streamIndex) + ipLen);
|
2015-04-16 11:50:07 -05:00
|
|
|
fv.resize(2);
|
|
|
|
qToBigEndian((quint16) totlen, (uchar*) fv.data());
|
|
|
|
return fv;
|
|
|
|
}
|
|
|
|
case FieldTextValue:
|
|
|
|
{
|
|
|
|
int totlen;
|
|
|
|
totlen = data.is_override_totlen() ? data.totlen() :
|
2016-10-27 13:20:24 -05:00
|
|
|
(protocolFramePayloadSize(streamIndex) + ipLen);
|
2015-04-16 11:50:07 -05:00
|
|
|
return QString("%1").arg(totlen);
|
|
|
|
}
|
|
|
|
case FieldBitSize:
|
|
|
|
return 16;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_id:
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Identification");
|
|
|
|
case FieldValue:
|
|
|
|
return data.id();
|
|
|
|
case FieldFrameValue:
|
|
|
|
{
|
|
|
|
QByteArray fv;
|
|
|
|
fv.resize(2);
|
|
|
|
qToBigEndian((quint16) data.id(), (uchar*)fv.data());
|
|
|
|
return fv;
|
|
|
|
}
|
|
|
|
case FieldTextValue:
|
|
|
|
return QString("0x%1").
|
|
|
|
arg(data.id(), 2, BASE_HEX, QChar('0'));;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ip4_flags:
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Flags");
|
|
|
|
case FieldValue:
|
|
|
|
return data.flags();
|
|
|
|
case FieldFrameValue:
|
|
|
|
return QByteArray(1, (char) data.flags());
|
|
|
|
case FieldTextValue:
|
|
|
|
{
|
|
|
|
QString s;
|
|
|
|
s.append("Unused:");
|
|
|
|
s.append(data.flags() & IP_FLAG_UNUSED ? "1" : "0");
|
|
|
|
s.append(" Don't Fragment:");
|
|
|
|
s.append(data.flags() & IP_FLAG_DF ? "1" : "0");
|
|
|
|
s.append(" More Fragments:");
|
|
|
|
s.append(data.flags() & IP_FLAG_MF ? "1" : "0");
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
case FieldBitSize:
|
|
|
|
return 3;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ip4_fragOfs:
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Fragment Offset");
|
|
|
|
case FieldValue:
|
|
|
|
return data.frag_ofs();
|
|
|
|
case FieldFrameValue:
|
|
|
|
{
|
|
|
|
QByteArray fv;
|
|
|
|
fv.resize(2);
|
|
|
|
qToBigEndian((quint16) (data.frag_ofs()),
|
|
|
|
(uchar*) fv.data());
|
|
|
|
return fv;
|
|
|
|
}
|
|
|
|
case FieldTextValue:
|
|
|
|
return QString("%1").arg(data.frag_ofs()*8);
|
|
|
|
case FieldBitSize:
|
|
|
|
return 13;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ip4_ttl:
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Time to Live");
|
|
|
|
case FieldValue:
|
|
|
|
return data.ttl();
|
|
|
|
case FieldFrameValue:
|
|
|
|
return QByteArray(1, (char)data.ttl());
|
|
|
|
case FieldTextValue:
|
|
|
|
return QString("%1").arg(data.ttl());
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ip4_proto:
|
|
|
|
{
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Protocol");
|
|
|
|
case FieldValue:
|
|
|
|
{
|
|
|
|
unsigned char id = data.is_override_proto() ?
|
|
|
|
data.proto() : payloadProtocolId(ProtocolIdIp);
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
case FieldFrameValue:
|
|
|
|
{
|
|
|
|
unsigned char id = data.is_override_proto() ?
|
|
|
|
data.proto() : payloadProtocolId(ProtocolIdIp);
|
|
|
|
return QByteArray(1, (char) id);
|
|
|
|
}
|
|
|
|
case FieldTextValue:
|
|
|
|
{
|
|
|
|
unsigned char id = data.is_override_proto() ?
|
|
|
|
data.proto() : payloadProtocolId(ProtocolIdIp);
|
|
|
|
return QString("0x%1").
|
|
|
|
arg(id, 2, BASE_HEX, QChar('0'));
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_cksum:
|
|
|
|
{
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Header Checksum");
|
|
|
|
case FieldValue:
|
|
|
|
{
|
|
|
|
quint16 cksum;
|
|
|
|
|
|
|
|
if (data.is_override_cksum())
|
|
|
|
cksum = data.cksum();
|
|
|
|
else
|
|
|
|
cksum = protocolFrameCksum(streamIndex, CksumIp);
|
|
|
|
return cksum;
|
|
|
|
}
|
|
|
|
case FieldFrameValue:
|
|
|
|
{
|
|
|
|
QByteArray fv;
|
|
|
|
quint16 cksum;
|
|
|
|
|
|
|
|
if (data.is_override_cksum())
|
|
|
|
cksum = data.cksum();
|
|
|
|
else
|
|
|
|
cksum = protocolFrameCksum(streamIndex, CksumIp);
|
|
|
|
|
|
|
|
fv.resize(2);
|
|
|
|
qToBigEndian((quint16) cksum, (uchar*) fv.data());
|
|
|
|
return fv;
|
|
|
|
}
|
|
|
|
case FieldTextValue:
|
|
|
|
{
|
|
|
|
quint16 cksum;
|
|
|
|
|
|
|
|
if (data.is_override_cksum())
|
|
|
|
cksum = data.cksum();
|
|
|
|
else
|
|
|
|
cksum = protocolFrameCksum(streamIndex, CksumIp);
|
|
|
|
return QString("0x%1").
|
|
|
|
arg(cksum, 4, BASE_HEX, QChar('0'));;
|
|
|
|
}
|
|
|
|
case FieldBitSize:
|
|
|
|
return 16;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_srcAddr:
|
|
|
|
{
|
|
|
|
int u;
|
|
|
|
quint32 subnet, host, srcIp = 0;
|
|
|
|
|
|
|
|
switch(data.src_ip_mode())
|
|
|
|
{
|
|
|
|
case OstProto::Ip4::e_im_fixed:
|
|
|
|
srcIp = data.src_ip();
|
|
|
|
break;
|
|
|
|
case OstProto::Ip4::e_im_inc_host:
|
|
|
|
u = streamIndex % data.src_ip_count();
|
|
|
|
subnet = data.src_ip() & data.src_ip_mask();
|
|
|
|
host = (((data.src_ip() & ~data.src_ip_mask()) + u) &
|
|
|
|
~data.src_ip_mask());
|
|
|
|
srcIp = subnet | host;
|
|
|
|
break;
|
|
|
|
case OstProto::Ip4::e_im_dec_host:
|
|
|
|
u = streamIndex % data.src_ip_count();
|
|
|
|
subnet = data.src_ip() & data.src_ip_mask();
|
|
|
|
host = (((data.src_ip() & ~data.src_ip_mask()) - u) &
|
|
|
|
~data.src_ip_mask());
|
|
|
|
srcIp = subnet | host;
|
|
|
|
break;
|
|
|
|
case OstProto::Ip4::e_im_random_host:
|
|
|
|
subnet = data.src_ip() & data.src_ip_mask();
|
|
|
|
host = (qrand() & ~data.src_ip_mask());
|
|
|
|
srcIp = subnet | host;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
qWarning("Unhandled src_ip_mode = %d", data.src_ip_mode());
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Source");
|
|
|
|
case FieldValue:
|
|
|
|
return srcIp;
|
|
|
|
case FieldFrameValue:
|
|
|
|
{
|
|
|
|
QByteArray fv;
|
|
|
|
fv.resize(4);
|
|
|
|
qToBigEndian(srcIp, (uchar*) fv.data());
|
|
|
|
return fv;
|
|
|
|
}
|
|
|
|
case FieldTextValue:
|
|
|
|
return QHostAddress(srcIp).toString();
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_dstAddr:
|
|
|
|
{
|
|
|
|
int u;
|
|
|
|
quint32 subnet, host, dstIp = 0;
|
|
|
|
|
|
|
|
switch(data.dst_ip_mode())
|
|
|
|
{
|
|
|
|
case OstProto::Ip4::e_im_fixed:
|
|
|
|
dstIp = data.dst_ip();
|
|
|
|
break;
|
|
|
|
case OstProto::Ip4::e_im_inc_host:
|
|
|
|
u = streamIndex % data.dst_ip_count();
|
|
|
|
subnet = data.dst_ip() & data.dst_ip_mask();
|
|
|
|
host = (((data.dst_ip() & ~data.dst_ip_mask()) + u) &
|
|
|
|
~data.dst_ip_mask());
|
|
|
|
dstIp = subnet | host;
|
|
|
|
break;
|
|
|
|
case OstProto::Ip4::e_im_dec_host:
|
|
|
|
u = streamIndex % data.dst_ip_count();
|
|
|
|
subnet = data.dst_ip() & data.dst_ip_mask();
|
|
|
|
host = (((data.dst_ip() & ~data.dst_ip_mask()) - u) &
|
|
|
|
~data.dst_ip_mask());
|
|
|
|
dstIp = subnet | host;
|
|
|
|
break;
|
|
|
|
case OstProto::Ip4::e_im_random_host:
|
|
|
|
subnet = data.dst_ip() & data.dst_ip_mask();
|
|
|
|
host = (qrand() & ~data.dst_ip_mask());
|
|
|
|
dstIp = subnet | host;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
qWarning("Unhandled dst_ip_mode = %d", data.dst_ip_mode());
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Destination");
|
|
|
|
case FieldValue:
|
|
|
|
return dstIp;
|
|
|
|
case FieldFrameValue:
|
|
|
|
{
|
|
|
|
QByteArray fv;
|
|
|
|
fv.resize(4);
|
|
|
|
qToBigEndian((quint32) dstIp, (uchar*) fv.data());
|
|
|
|
return fv;
|
|
|
|
}
|
|
|
|
case FieldTextValue:
|
|
|
|
return QHostAddress(dstIp).toString();
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-10-27 13:20:24 -05:00
|
|
|
case ip4_options:
|
|
|
|
{
|
|
|
|
QByteArray ba;
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue:
|
|
|
|
case FieldFrameValue:
|
|
|
|
case FieldTextValue:
|
2018-09-13 01:59:13 -05:00
|
|
|
ba.append(data.options().c_str(), data.options().length());
|
2016-10-27 13:20:24 -05:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldName:
|
|
|
|
return QString("Options");
|
|
|
|
case FieldValue:
|
|
|
|
case FieldFrameValue:
|
|
|
|
return ba;
|
|
|
|
case FieldTextValue:
|
|
|
|
return ba.toHex();
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2015-04-16 11:50:07 -05:00
|
|
|
|
|
|
|
// Meta fields
|
|
|
|
case ip4_isOverrideVer:
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue: return data.is_override_ver();
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ip4_isOverrideHdrLen:
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue: return data.is_override_hdrlen();
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ip4_isOverrideTotLen:
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue: return data.is_override_totlen();
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ip4_isOverrideProto:
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue: return data.is_override_proto();
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ip4_isOverrideCksum:
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue: return data.is_override_cksum();
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ip4_srcAddrMode:
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue: return data.src_ip_mode();
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ip4_srcAddrCount:
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue: return data.src_ip_count();
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ip4_srcAddrMask:
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue: return data.src_ip_mask();
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ip4_dstAddrMode:
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue: return data.dst_ip_mode();
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ip4_dstAddrCount:
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue: return data.dst_ip_count();
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ip4_dstAddrMask:
|
|
|
|
switch(attrib)
|
|
|
|
{
|
|
|
|
case FieldValue: return data.dst_ip_mask();
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return AbstractProtocol::fieldData(index, attrib, streamIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Ip4Protocol::setFieldData(int index, const QVariant &value,
|
|
|
|
FieldAttrib attrib)
|
|
|
|
{
|
|
|
|
bool isOk = false;
|
|
|
|
|
|
|
|
if (attrib != FieldValue)
|
|
|
|
goto _exit;
|
|
|
|
|
|
|
|
switch (index)
|
|
|
|
{
|
|
|
|
case ip4_ver:
|
|
|
|
{
|
|
|
|
uint version = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_ver_hdrlen(
|
|
|
|
((version & 0xF) << 4)
|
|
|
|
| (data.ver_hdrlen() & 0x0F));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_hdrLen:
|
|
|
|
{
|
|
|
|
uint hdrLen = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_ver_hdrlen(
|
|
|
|
(data.ver_hdrlen() & 0xF0)
|
|
|
|
| (hdrLen & 0x0F));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_tos:
|
|
|
|
{
|
|
|
|
uint tos = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_tos(tos);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_totLen:
|
|
|
|
{
|
|
|
|
uint totLen = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_totlen(totLen);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_id:
|
|
|
|
{
|
|
|
|
uint id = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_id(id);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_flags:
|
|
|
|
{
|
|
|
|
uint flags = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_flags(flags);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_fragOfs:
|
|
|
|
{
|
|
|
|
uint fragOfs = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_frag_ofs(fragOfs);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_ttl:
|
|
|
|
{
|
|
|
|
uint ttl = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_ttl(ttl);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_proto:
|
|
|
|
{
|
|
|
|
uint proto = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_proto(proto);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_cksum:
|
|
|
|
{
|
|
|
|
uint cksum = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_cksum(cksum);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_srcAddr:
|
|
|
|
{
|
|
|
|
quint32 srcIp = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_src_ip(srcIp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_dstAddr:
|
|
|
|
{
|
|
|
|
quint32 dstIp = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_dst_ip(dstIp);
|
|
|
|
break;
|
|
|
|
}
|
2016-10-27 13:20:24 -05:00
|
|
|
case ip4_options:
|
|
|
|
{
|
|
|
|
QByteArray ba = value.toByteArray();
|
|
|
|
int pad = (4 - (ba.size() % 4)) % 4;
|
|
|
|
if (pad)
|
|
|
|
ba.append(QByteArray(pad, 0));
|
|
|
|
data.set_options(ba.constData(), ba.size());
|
|
|
|
isOk = true;
|
|
|
|
break;
|
|
|
|
}
|
2015-04-16 11:50:07 -05:00
|
|
|
|
|
|
|
// Meta-fields
|
|
|
|
case ip4_isOverrideVer:
|
|
|
|
{
|
|
|
|
bool ovr = value.toBool();
|
|
|
|
data.set_is_override_ver(ovr);
|
|
|
|
isOk = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_isOverrideHdrLen:
|
|
|
|
{
|
|
|
|
bool ovr = value.toBool();
|
|
|
|
data.set_is_override_hdrlen(ovr);
|
|
|
|
isOk = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_isOverrideTotLen:
|
|
|
|
{
|
|
|
|
bool ovr = value.toBool();
|
|
|
|
data.set_is_override_totlen(ovr);
|
|
|
|
isOk = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_isOverrideProto:
|
|
|
|
{
|
|
|
|
bool ovr = value.toBool();
|
|
|
|
data.set_is_override_proto(ovr);
|
|
|
|
isOk = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_isOverrideCksum:
|
|
|
|
{
|
|
|
|
bool ovr = value.toBool();
|
|
|
|
data.set_is_override_cksum(ovr);
|
|
|
|
isOk = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case ip4_srcAddrMode:
|
|
|
|
{
|
|
|
|
uint mode = value.toUInt(&isOk);
|
|
|
|
if (isOk && data.IpAddrMode_IsValid(mode))
|
|
|
|
data.set_src_ip_mode(OstProto::Ip4::IpAddrMode(mode));
|
|
|
|
else
|
|
|
|
isOk = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_srcAddrCount:
|
|
|
|
{
|
|
|
|
uint count = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_src_ip_count(count);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_srcAddrMask:
|
|
|
|
{
|
|
|
|
quint32 mask = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_src_ip_mask(mask);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case ip4_dstAddrMode:
|
|
|
|
{
|
|
|
|
uint mode = value.toUInt(&isOk);
|
|
|
|
if (isOk && data.IpAddrMode_IsValid(mode))
|
|
|
|
data.set_dst_ip_mode(OstProto::Ip4::IpAddrMode(mode));
|
|
|
|
else
|
|
|
|
isOk = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_dstAddrCount:
|
|
|
|
{
|
|
|
|
uint count = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_dst_ip_count(count);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ip4_dstAddrMask:
|
|
|
|
{
|
|
|
|
quint32 mask = value.toUInt(&isOk);
|
|
|
|
if (isOk)
|
|
|
|
data.set_dst_ip_mask(mask);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
qFatal("%s: unimplemented case %d in switch", __PRETTY_FUNCTION__,
|
|
|
|
index);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
_exit:
|
|
|
|
return isOk;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Ip4Protocol::protocolFrameVariableCount() const
|
|
|
|
{
|
2015-05-26 11:13:37 -05:00
|
|
|
int count = AbstractProtocol::protocolFrameVariableCount();
|
2015-04-16 11:50:07 -05:00
|
|
|
|
|
|
|
if (data.src_ip_mode() != OstProto::Ip4::e_im_fixed)
|
|
|
|
count = AbstractProtocol::lcm(count, data.src_ip_count());
|
|
|
|
|
|
|
|
if (data.dst_ip_mode() != OstProto::Ip4::e_im_fixed)
|
|
|
|
count = AbstractProtocol::lcm(count, data.dst_ip_count());
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
quint32 Ip4Protocol::protocolFrameCksum(int streamIndex,
|
2021-09-04 07:46:40 -05:00
|
|
|
CksumType cksumType, CksumFlags cksumFlags) const
|
2015-04-16 11:50:07 -05:00
|
|
|
{
|
|
|
|
switch (cksumType)
|
|
|
|
{
|
|
|
|
case CksumIpPseudo:
|
|
|
|
{
|
2015-05-26 11:13:37 -05:00
|
|
|
quint32 sum = 0;
|
|
|
|
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
|
|
|
sum += *((quint16*)(p + 12)); // src-ip hi
|
|
|
|
sum += *((quint16*)(p + 14)); // src-ip lo
|
|
|
|
sum += *((quint16*)(p + 16)); // dst-ip hi
|
|
|
|
sum += *((quint16*)(p + 18)); // dst-ip lo
|
2018-09-13 02:02:36 -05:00
|
|
|
|
|
|
|
// XXX: payload length and protocol are also part of the
|
|
|
|
// pseudo cksum but for IPv6 we need to skip extension headers to
|
|
|
|
// get to them, so these two fields are counted in the
|
|
|
|
// pseudo cksum in AbstractProtocol::protocolFrameHeaderCksum()
|
|
|
|
// Although not needed for IPv4 case, we do the same for IPv4
|
|
|
|
// also, so that code there is common for IPv4 and IPv6
|
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
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
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 Ip4Protocol::hasErrors(QStringList *errors) const
|
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
|
|
|
|
if ((data.dst_ip() == 0)
|
|
|
|
&& (data.dst_ip_mode() == OstProto::Ip4::e_im_fixed)) {
|
|
|
|
if (errors)
|
|
|
|
*errors << QObject::tr("Frames with Destination IP 0.0.0.0 "
|
|
|
|
"are likely to be dropped");
|
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((data.src_ip() == 0)
|
|
|
|
&& (data.src_ip_mode() == OstProto::Ip4::e_im_fixed)) {
|
|
|
|
if (errors)
|
|
|
|
*errors << QObject::tr("Frames with Source IP 0.0.0.0 "
|
|
|
|
"may be dropped except for special cases "
|
|
|
|
"like BOOTP/DHCP");
|
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|