- Top level Makefile

- The default 'all' target no longer has 'qmake' as prerequisite; 'make qmake' shd be done manually on a pristine codebase
    - eol's changed from dos-style to unix-style
- Trivial changes in sample.h/sample.cpp
- Implemented ARP protocol
This commit is contained in:
Srivats P. 2010-03-13 05:46:24 +00:00
parent 3281eb8f20
commit f64d901729
11 changed files with 1679 additions and 47 deletions

View File

@ -1,26 +1,29 @@
release: QMAKE_CONFIG=-config release
all release: qmake
$(MAKE) -C rpc
$(MAKE) -C common
$(MAKE) -C server
$(MAKE) -C client
clean:
$(MAKE) -C rpc $@
$(MAKE) -C common $@
$(MAKE) -C server $@
$(MAKE) -C client $@
distclean:
$(MAKE) -C rpc $@
$(MAKE) -C common $@
$(MAKE) -C server $@
$(MAKE) -C client $@
qmake:
cd rpc && qmake $(QMAKE_CONFIG) && cd ..
cd common && qmake $(QMAKE_CONFIG) && cd ..
cd server && qmake $(QMAKE_CONFIG) && cd ..
cd client && qmake $(QMAKE_CONFIG) && cd ..
release: QMAKE_CONFIG=-config release
all:
$(MAKE) -C rpc
$(MAKE) -C common
$(MAKE) -C server
$(MAKE) -C client
release: qmake all
clean:
$(MAKE) -C rpc $@
$(MAKE) -C common $@
$(MAKE) -C server $@
$(MAKE) -C client $@
distclean:
$(MAKE) -C rpc $@
$(MAKE) -C common $@
$(MAKE) -C server $@
$(MAKE) -C client $@
qmake:
cd rpc && qmake $(QMAKE_CONFIG) && cd ..
cd common && qmake $(QMAKE_CONFIG) && cd ..
cd server && qmake $(QMAKE_CONFIG) && cd ..
cd client && qmake $(QMAKE_CONFIG) && cd ..

View File

@ -123,8 +123,7 @@ StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex,
// TODO(MED):
//! \todo Implement then enable these protocols - ARP, IPv6, ICMP, IGMP
rbL3Arp->setHidden(true);
//! \todo Implement then enable these protocols - IPv6, ICMP, IGMP
rbL3Ipv6->setHidden(true);
rbL4Icmp->setHidden(true);
rbL4Igmp->setHidden(true);
@ -179,7 +178,7 @@ void StreamConfigDialog::setupUiExtra()
bgProto[ProtoL3]->addButton(rbL3None, ButtonIdNone);
bgProto[ProtoL3]->addButton(rbL3Ipv4, OstProto::Protocol::kIp4FieldNumber);
bgProto[ProtoL3]->addButton(rbL3Ipv6, 0xFFFF);
bgProto[ProtoL3]->addButton(rbL3Arp, 0xFFFF);
bgProto[ProtoL3]->addButton(rbL3Arp, OstProto::Protocol::kArpFieldNumber);
bgProto[ProtoL3]->addButton(rbL3Other, ButtonIdOther);
#endif
@ -191,8 +190,8 @@ void StreamConfigDialog::setupUiExtra()
bgProto[ProtoL4]->addButton(rbL4None, 0);
bgProto[ProtoL4]->addButton(rbL4Tcp, OstProto::Protocol::kTcpFieldNumber);
bgProto[ProtoL4]->addButton(rbL4Udp, OstProto::Protocol::kUdpFieldNumber);
bgProto[ProtoL4]->addButton(rbL4Icmp, 0xFFFF);
bgProto[ProtoL4]->addButton(rbL4Igmp, 0xFFFF);
bgProto[ProtoL4]->addButton(rbL4Icmp, OstProto::Protocol::kIcmpFieldNumber);
bgProto[ProtoL4]->addButton(rbL4Igmp, OstProto::Protocol::kIgmpFieldNumber);
bgProto[ProtoL4]->addButton(rbL4Other, ButtonIdOther);
#endif

925
common/arp.cpp Normal file
View File

@ -0,0 +1,925 @@
#include <qendian.h>
#include <QHostAddress>
#include "arp.h"
ArpConfigForm::ArpConfigForm(QWidget *parent)
: QWidget(parent)
{
setupUi(this);
opCodeCombo->setValidator(new QIntValidator(0, 0xFFFF, this));
opCodeCombo->addItem(1, "ARP Request");
opCodeCombo->addItem(2, "ARP Reply");
connect(senderHwAddrMode, SIGNAL(currentIndexChanged(int)),
SLOT(on_senderHwAddrMode_currentIndexChanged(int)));
connect(senderProtoAddrMode, SIGNAL(currentIndexChanged(int)),
SLOT(on_senderProtoAddrMode_currentIndexChanged(int)));
connect(targetHwAddrMode, SIGNAL(currentIndexChanged(int)),
SLOT(on_targetHwAddrMode_currentIndexChanged(int)));
connect(targetProtoAddrMode, SIGNAL(currentIndexChanged(int)),
SLOT(on_targetProtoAddrMode_currentIndexChanged(int)));
}
void ArpConfigForm::on_senderHwAddrMode_currentIndexChanged(int index)
{
if (index == OstProto::Arp::kFixed)
senderHwAddrCount->setDisabled(true);
else
senderHwAddrCount->setEnabled(true);
}
void ArpConfigForm::on_targetHwAddrMode_currentIndexChanged(int index)
{
if (index == OstProto::Arp::kFixed)
targetHwAddrCount->setDisabled(true);
else
targetHwAddrCount->setEnabled(true);
}
void ArpConfigForm::on_senderProtoAddrMode_currentIndexChanged(int index)
{
if (index == OstProto::Arp::kFixedHost)
{
senderProtoAddrCount->setDisabled(true);
senderProtoAddrMask->setDisabled(true);
}
else
{
senderProtoAddrCount->setEnabled(true);
senderProtoAddrMask->setEnabled(true);
}
}
void ArpConfigForm::on_targetProtoAddrMode_currentIndexChanged(int index)
{
if (index == OstProto::Arp::kFixedHost)
{
targetProtoAddrCount->setDisabled(true);
targetProtoAddrMask->setDisabled(true);
}
else
{
targetProtoAddrCount->setEnabled(true);
targetProtoAddrMask->setEnabled(true);
}
}
ArpProtocol::ArpProtocol(StreamBase *stream, AbstractProtocol *parent)
: AbstractProtocol(stream, parent)
{
configForm = NULL;
}
ArpProtocol::~ArpProtocol()
{
delete configForm;
}
AbstractProtocol* ArpProtocol::createInstance(StreamBase *stream,
AbstractProtocol *parent)
{
return new ArpProtocol(stream, parent);
}
quint32 ArpProtocol::protocolNumber() const
{
return OstProto::Protocol::kArpFieldNumber;
}
void ArpProtocol::protoDataCopyInto(OstProto::Protocol &protocol) const
{
protocol.MutableExtension(OstProto::arp)->CopyFrom(data);
protocol.mutable_protocol_id()->set_id(protocolNumber());
}
void ArpProtocol::protoDataCopyFrom(const OstProto::Protocol &protocol)
{
if (protocol.protocol_id().id() == protocolNumber() &&
protocol.HasExtension(OstProto::arp))
data.MergeFrom(protocol.GetExtension(OstProto::arp));
}
QString ArpProtocol::name() const
{
return QString("Address Resolution Protocol");
}
QString ArpProtocol::shortName() const
{
return QString("ARP");
}
/*!
Return the ProtocolIdType for your protocol \n
If your protocol doesn't have a protocolId field, you don't need to
reimplement this method - the base class implementation will do the
right thing
*/
#if 0
AbstractProtocol::ProtocolIdType ArpProtocol::protocolIdType() const
{
return ProtocolIdIp;
}
#endif
/*!
Return the protocolId for your protocol based on the 'type' requested \n
If not all types are valid for your protocol, handle the valid type(s)
and for the remaining fallback to the base class implementation; if your
protocol doesn't have a protocolId at all, you don't need to reimplement
this method - the base class will do the right thing
*/
quint32 ArpProtocol::protocolId(ProtocolIdType type) const
{
switch(type)
{
case ProtocolIdEth: return 0x0806;
default:break;
}
return AbstractProtocol::protocolId(type);
}
int ArpProtocol::fieldCount() const
{
return arp_fieldCount;
}
AbstractProtocol::FieldFlags ArpProtocol::fieldFlags(int index) const
{
AbstractProtocol::FieldFlags flags;
flags = AbstractProtocol::fieldFlags(index);
switch (index)
{
case arp_hwType:
case arp_protoType:
case arp_hwAddrLen:
case arp_protoAddrLen:
case arp_opCode:
case arp_senderHwAddr:
case arp_senderProtoAddr:
case arp_targetHwAddr:
case arp_targetProtoAddr:
break;
case arp_senderHwAddrMode:
case arp_senderHwAddrCount:
case arp_senderProtoAddrMode:
case arp_senderProtoAddrCount:
case arp_senderProtoAddrMask:
case arp_targetHwAddrMode:
case arp_targetHwAddrCount:
case arp_targetProtoAddrMode:
case arp_targetProtoAddrCount:
case arp_targetProtoAddrMask:
flags |= FieldIsMeta;
break;
default:
qFatal("%s: unimplemented case %d in switch", __PRETTY_FUNCTION__,
index);
break;
}
return flags;
}
QVariant ArpProtocol::fieldData(int index, FieldAttrib attrib,
int streamIndex) const
{
switch (index)
{
case arp_hwType:
{
switch(attrib)
{
case FieldName:
return QString("Hardware Type");
case FieldValue:
return data.hw_type();
case FieldTextValue:
return QString("%1").arg(data.hw_type());
case FieldFrameValue:
{
QByteArray fv;
fv.resize(2);
qToBigEndian((quint16) data.hw_type(), (uchar*) fv.data());
return fv;
}
default:
break;
}
break;
}
case arp_protoType:
{
switch(attrib)
{
case FieldName:
return QString("Protocol Type");
case FieldValue:
return data.proto_type();
case FieldTextValue:
return QString("%1").arg(data.proto_type(), 4, BASE_HEX,
QChar('0'));
case FieldFrameValue:
{
QByteArray fv;
fv.resize(2);
qToBigEndian((quint16) data.proto_type(), (uchar*) fv.data());
return fv;
}
default:
break;
}
break;
}
case arp_hwAddrLen:
{
switch(attrib)
{
case FieldName:
return QString("Hardware Address Length");
case FieldValue:
return data.hw_addr_len();
case FieldTextValue:
return QString("%1").arg(data.hw_addr_len());
case FieldFrameValue:
return QByteArray(1, (char) data.hw_addr_len());
default:
break;
}
break;
}
case arp_protoAddrLen:
{
switch(attrib)
{
case FieldName:
return QString("Protocol Address Length");
case FieldValue:
return data.proto_addr_len();
case FieldTextValue:
return QString("%1").arg(data.proto_addr_len());
case FieldFrameValue:
return QByteArray(1, (char) data.proto_addr_len());
default:
break;
}
break;
}
case arp_opCode:
{
switch(attrib)
{
case FieldName:
return QString("Operation Code");
case FieldValue:
return data.op_code();
case FieldTextValue:
return QString("%1").arg(data.op_code());
case FieldFrameValue:
{
QByteArray fv;
fv.resize(2);
qToBigEndian((quint16) data.op_code(), (uchar*) fv.data());
return fv;
}
default:
break;
}
break;
}
case arp_senderHwAddr:
{
int u;
const int hwAddrStep = 1;
quint64 hwAddr = 0;
switch (data.sender_hw_addr_mode())
{
case OstProto::Arp::kFixed:
hwAddr = data.sender_hw_addr();
break;
case OstProto::Arp::kIncrement:
u = (streamIndex % data.sender_hw_addr_count()) *
hwAddrStep;
hwAddr = data.sender_hw_addr() + u;
break;
case OstProto::Arp::kDecrement:
u = (streamIndex % data.sender_hw_addr_count()) *
hwAddrStep;
hwAddr = data.sender_hw_addr() - u;
break;
default:
qWarning("Unhandled hw_addr_mode %d",
data.sender_hw_addr_mode());
}
switch(attrib)
{
case FieldName:
return QString("Sender Hardware Address");
case FieldValue:
return hwAddr;
case FieldTextValue:
return uintToHexStr(hwAddr, 6);
case FieldFrameValue:
{
QByteArray fv;
fv.resize(8);
qToBigEndian((quint64) hwAddr, (uchar*) fv.data());
fv.remove(0, 2);
return fv;
}
default:
break;
}
break;
}
case arp_senderProtoAddr:
{
int u;
quint32 subnet, host, protoAddr = 0;
switch(data.sender_proto_addr_mode())
{
case OstProto::Arp::kFixedHost:
protoAddr = data.sender_proto_addr();
break;
case OstProto::Arp::kIncrementHost:
u = streamIndex % data.sender_proto_addr_count();
subnet = data.sender_proto_addr()
& data.sender_proto_addr_mask();
host = (((data.sender_proto_addr()
& ~data.sender_proto_addr_mask()) + u)
& ~data.sender_proto_addr_mask());
protoAddr = subnet | host;
break;
case OstProto::Arp::kDecrementHost:
u = streamIndex % data.sender_proto_addr_count();
subnet = data.sender_proto_addr()
& data.sender_proto_addr_mask();
host = (((data.sender_proto_addr()
& ~data.sender_proto_addr_mask()) - u)
& ~data.sender_proto_addr_mask());
protoAddr = subnet | host;
break;
case OstProto::Arp::kRandomHost:
subnet = data.sender_proto_addr()
& data.sender_proto_addr_mask();
host = (qrand() & ~data.sender_proto_addr_mask());
protoAddr = subnet | host;
break;
default:
qWarning("Unhandled sender_proto_addr_mode = %d",
data.sender_proto_addr_mode());
}
switch(attrib)
{
case FieldName:
return QString("Sender Protocol Address");
case FieldValue:
return protoAddr;
case FieldFrameValue:
{
QByteArray fv;
fv.resize(4);
qToBigEndian((quint32) protoAddr, (uchar*) fv.data());
return fv;
}
case FieldTextValue:
return QHostAddress(protoAddr).toString();
default:
break;
}
break;
}
case arp_targetHwAddr:
{
int u;
const int hwAddrStep = 1;
quint64 hwAddr = 0;
switch (data.target_hw_addr_mode())
{
case OstProto::Arp::kFixed:
hwAddr = data.target_hw_addr();
break;
case OstProto::Arp::kIncrement:
u = (streamIndex % data.target_hw_addr_count()) *
hwAddrStep;
hwAddr = data.target_hw_addr() + u;
break;
case OstProto::Arp::kDecrement:
u = (streamIndex % data.target_hw_addr_count()) *
hwAddrStep;
hwAddr = data.target_hw_addr() - u;
break;
default:
qWarning("Unhandled hw_addr_mode %d",
data.target_hw_addr_mode());
}
switch(attrib)
{
case FieldName:
return QString("Target Hardware Address");
case FieldValue:
return hwAddr;
case FieldTextValue:
return uintToHexStr(hwAddr, 6);
case FieldFrameValue:
{
QByteArray fv;
fv.resize(8);
qToBigEndian((quint64) hwAddr, (uchar*) fv.data());
fv.remove(0, 2);
return fv;
}
default:
break;
}
break;
}
case arp_targetProtoAddr:
{
int u;
quint32 subnet, host, protoAddr = 0;
switch(data.target_proto_addr_mode())
{
case OstProto::Arp::kFixed:
protoAddr = data.target_proto_addr();
break;
case OstProto::Arp::kIncrementHost:
u = streamIndex % data.target_proto_addr_count();
subnet = data.target_proto_addr()
& data.target_proto_addr_mask();
host = (((data.target_proto_addr()
& ~data.target_proto_addr_mask()) + u)
& ~data.target_proto_addr_mask());
protoAddr = subnet | host;
break;
case OstProto::Arp::kDecrementHost:
u = streamIndex % data.target_proto_addr_count();
subnet = data.target_proto_addr()
& data.target_proto_addr_mask();
host = (((data.target_proto_addr()
& ~data.target_proto_addr_mask()) - u)
& ~data.target_proto_addr_mask());
protoAddr = subnet | host;
break;
case OstProto::Arp::kRandomHost:
subnet = data.target_proto_addr()
& data.target_proto_addr_mask();
host = (qrand() & ~data.target_proto_addr_mask());
protoAddr = subnet | host;
break;
default:
qWarning("Unhandled target_proto_addr_mode = %d",
data.target_proto_addr_mode());
}
switch(attrib)
{
case FieldName:
return QString("Target Protocol Address");
case FieldValue:
return protoAddr;
case FieldFrameValue:
{
QByteArray fv;
fv.resize(4);
qToBigEndian((quint32) protoAddr, (uchar*) fv.data());
return fv;
}
case FieldTextValue:
return QHostAddress(protoAddr).toString();
default:
break;
}
break;
}
// Meta fields
case arp_senderHwAddrMode:
switch(attrib)
{
case FieldName:
return QString("Sender Hardware Address Mode");
case FieldValue:
return data.sender_hw_addr_mode();
default:
break;
}
break;
case arp_senderHwAddrCount:
switch(attrib)
{
case FieldName:
return QString("Sender Hardware Address Count");
case FieldValue:
return data.sender_hw_addr_count();
default:
break;
}
break;
case arp_senderProtoAddrMode:
switch(attrib)
{
case FieldName:
return QString("Sender Protocol Address Mode");
case FieldValue:
return data.sender_proto_addr_mode();
default:
break;
}
break;
case arp_senderProtoAddrCount:
switch(attrib)
{
case FieldName:
return QString("Sender Protocol Address Count");
case FieldValue:
return data.sender_proto_addr_count();
default:
break;
}
break;
case arp_senderProtoAddrMask:
switch(attrib)
{
case FieldName:
return QString("Sender Protocol Address Mask");
case FieldValue:
return data.sender_proto_addr_mask();
default:
break;
}
break;
case arp_targetHwAddrMode:
switch(attrib)
{
case FieldName:
return QString("Target Hardware Address Mode");
case FieldValue:
return data.target_hw_addr_mode();
default:
break;
}
break;
case arp_targetHwAddrCount:
switch(attrib)
{
case FieldName:
return QString("Target Hardware Address Count");
case FieldValue:
return data.target_hw_addr_count();
default:
break;
}
break;
case arp_targetProtoAddrMode:
switch(attrib)
{
case FieldName:
return QString("Target Protocol Address Mode");
case FieldValue:
return data.target_proto_addr_mode();
default:
break;
}
break;
case arp_targetProtoAddrCount:
switch(attrib)
{
case FieldName:
return QString("Target Protocol Address Count");
case FieldValue:
return data.target_proto_addr_count();
default:
break;
}
break;
case arp_targetProtoAddrMask:
switch(attrib)
{
case FieldName:
return QString("Target Protocol Address Mask");
case FieldValue:
return data.target_proto_addr_mask();
default:
break;
}
break;
default:
qFatal("%s: unimplemented case %d in switch", __PRETTY_FUNCTION__,
index);
break;
}
return AbstractProtocol::fieldData(index, attrib, streamIndex);
}
bool ArpProtocol::setFieldData(int index, const QVariant &value,
FieldAttrib attrib)
{
bool isOk = false;
if (attrib != FieldValue)
goto _exit;
switch (index)
{
case arp_hwType:
{
uint hwType = value.toUInt(&isOk);
if (isOk)
data.set_hw_type(hwType);
break;
}
case arp_protoType:
{
uint protoType = value.toUInt(&isOk);
if (isOk)
data.set_proto_type(protoType);
break;
}
case arp_hwAddrLen:
{
uint hwAddrLen = value.toUInt(&isOk);
if (isOk)
data.set_hw_addr_len(hwAddrLen);
break;
}
case arp_protoAddrLen:
{
uint protoAddrLen = value.toUInt(&isOk);
if (isOk)
data.set_proto_addr_len(protoAddrLen);
break;
}
case arp_opCode:
{
uint opCode = value.toUInt(&isOk);
if (isOk)
data.set_op_code(opCode);
break;
}
case arp_senderHwAddr:
{
quint64 hwAddr = value.toULongLong(&isOk);
if (isOk)
data.set_sender_hw_addr(hwAddr);
break;
}
case arp_senderHwAddrMode:
{
uint mode = value.toUInt(&isOk);
if (isOk && data.HwAddrMode_IsValid(mode))
data.set_sender_hw_addr_mode((OstProto::Arp::HwAddrMode) mode);
break;
}
case arp_senderHwAddrCount:
{
uint count = value.toUInt(&isOk);
if (isOk)
data.set_sender_hw_addr_count(count);
break;
}
case arp_senderProtoAddr:
{
uint protoAddr = value.toUInt(&isOk);
if (isOk)
data.set_sender_proto_addr(protoAddr);
break;
}
case arp_senderProtoAddrMode:
{
uint mode = value.toUInt(&isOk);
if (isOk && data.ProtoAddrMode_IsValid(mode))
data.set_sender_proto_addr_mode(
(OstProto::Arp::ProtoAddrMode)mode);
break;
}
case arp_senderProtoAddrCount:
{
uint count = value.toUInt(&isOk);
if (isOk)
data.set_sender_proto_addr_count(count);
break;
}
case arp_senderProtoAddrMask:
{
uint mask = value.toUInt(&isOk);
if (isOk)
data.set_sender_proto_addr_mask(mask);
break;
}
case arp_targetHwAddr:
{
quint64 hwAddr = value.toULongLong(&isOk);
if (isOk)
data.set_target_hw_addr(hwAddr);
break;
}
case arp_targetHwAddrMode:
{
uint mode = value.toUInt(&isOk);
if (isOk && data.HwAddrMode_IsValid(mode))
data.set_target_hw_addr_mode((OstProto::Arp::HwAddrMode)mode);
break;
}
case arp_targetHwAddrCount:
{
uint count = value.toUInt(&isOk);
if (isOk)
data.set_target_hw_addr_count(count);
break;
}
case arp_targetProtoAddr:
{
uint protoAddr = value.toUInt(&isOk);
if (isOk)
data.set_target_proto_addr(protoAddr);
break;
}
case arp_targetProtoAddrMode:
{
uint mode = value.toUInt(&isOk);
if (isOk && data.ProtoAddrMode_IsValid(mode))
data.set_target_proto_addr_mode(
(OstProto::Arp::ProtoAddrMode)mode);
break;
}
case arp_targetProtoAddrCount:
{
uint count = value.toUInt(&isOk);
if (isOk)
data.set_target_proto_addr_count(count);
break;
}
case arp_targetProtoAddrMask:
{
uint mask = value.toUInt(&isOk);
if (isOk)
data.set_target_proto_addr_mask(mask);
break;
}
default:
qFatal("%s: unimplemented case %d in switch", __PRETTY_FUNCTION__,
index);
break;
}
_exit:
return isOk;
}
/*!
If your protocol has any variable fields, return true \n
Otherwise you don't need to reimplement this method - the base class always
returns false
*/
bool ArpProtocol::isProtocolFrameValueVariable() const
{
return true;
}
QWidget* ArpProtocol::configWidget()
{
if (configForm == NULL)
{
configForm = new ArpConfigForm;
loadConfigWidget();
}
return configForm;
}
void ArpProtocol::loadConfigWidget()
{
configWidget();
configForm->hwType->setText(
fieldData(arp_hwType, FieldValue).toString());
configForm->protoType->setText(uintToHexStr(
fieldData(arp_protoType, FieldValue).toUInt(), 2));
configForm->hwAddrLen->setText(
fieldData(arp_hwAddrLen, FieldValue).toString());
configForm->protoAddrLen->setText(
fieldData(arp_protoAddrLen, FieldValue).toString());
configForm->opCodeCombo->setValue(
fieldData(arp_opCode, FieldValue).toUInt());
configForm->senderHwAddr->setText(uintToHexStr(
fieldData(arp_senderHwAddr, FieldValue).toULongLong(), 6));
configForm->senderHwAddrMode->setCurrentIndex(
fieldData(arp_senderHwAddrMode, FieldValue).toUInt());
configForm->senderHwAddrCount->setText(
fieldData(arp_senderHwAddrCount, FieldValue).toString());
configForm->senderProtoAddr->setText(QHostAddress(
fieldData(arp_senderProtoAddr, FieldValue).toUInt()).toString());
configForm->senderProtoAddrMode->setCurrentIndex(
fieldData(arp_senderProtoAddrMode, FieldValue).toUInt());
configForm->senderProtoAddrCount->setText(
fieldData(arp_senderProtoAddrCount, FieldValue).toString());
configForm->senderProtoAddrMask->setText(QHostAddress(
fieldData(arp_senderProtoAddrMask, FieldValue).toUInt()).toString());
configForm->targetHwAddr->setText(uintToHexStr(
fieldData(arp_targetHwAddr, FieldValue).toULongLong(), 6));
configForm->targetHwAddrMode->setCurrentIndex(
fieldData(arp_targetHwAddrMode, FieldValue).toUInt());
configForm->targetHwAddrCount->setText(
fieldData(arp_targetHwAddrCount, FieldValue).toString());
configForm->targetProtoAddr->setText(QHostAddress(
fieldData(arp_targetProtoAddr, FieldValue).toUInt()).toString());
configForm->targetProtoAddrMode->setCurrentIndex(
fieldData(arp_targetProtoAddrMode, FieldValue).toUInt());
configForm->targetProtoAddrCount->setText(
fieldData(arp_targetProtoAddrCount, FieldValue).toString());
configForm->targetProtoAddrMask->setText(QHostAddress(
fieldData(arp_targetProtoAddrMask, FieldValue).toUInt()).toString());
}
void ArpProtocol::storeConfigWidget()
{
bool isOk;
configWidget();
setFieldData(arp_hwType, configForm->hwType->text());
setFieldData(arp_protoType, configForm->protoType->text().toUInt(
&isOk, BASE_HEX));
setFieldData(arp_hwAddrLen, configForm->hwAddrLen->text());
setFieldData(arp_protoAddrLen, configForm->protoAddrLen->text());
setFieldData(arp_opCode, configForm->opCodeCombo->currentValue());
setFieldData(arp_senderHwAddr, configForm->senderHwAddr->text()
.remove(QChar(' ')).toULongLong(&isOk, BASE_HEX));
setFieldData(arp_senderHwAddrMode,
configForm->senderHwAddrMode->currentIndex());
setFieldData(arp_senderHwAddrCount, configForm->senderHwAddrCount->text());
setFieldData(arp_senderProtoAddr, QHostAddress(
configForm->senderProtoAddr->text()).toIPv4Address());
setFieldData(arp_senderProtoAddrMode,
configForm->senderProtoAddrMode->currentIndex());
setFieldData(arp_senderProtoAddrCount,
configForm->senderProtoAddrCount->text());
setFieldData(arp_senderProtoAddrMask, QHostAddress(
configForm->senderProtoAddrMask->text()).toIPv4Address());
setFieldData(arp_targetHwAddr, configForm->targetHwAddr->text()
.remove(QChar(' ')).toULongLong(&isOk, BASE_HEX));
setFieldData(arp_targetHwAddrMode,
configForm->targetHwAddrMode->currentIndex());
setFieldData(arp_targetHwAddrCount, configForm->targetHwAddrCount->text());
setFieldData(arp_targetProtoAddr, QHostAddress(
configForm->targetProtoAddr->text()).toIPv4Address());
setFieldData(arp_targetProtoAddrMode,
configForm->targetProtoAddrMode->currentIndex());
setFieldData(arp_targetProtoAddrCount,
configForm->targetProtoAddrCount->text());
setFieldData(arp_targetProtoAddrMask, QHostAddress(
configForm->targetProtoAddrMask->text()).toIPv4Address());
}

101
common/arp.h Normal file
View File

@ -0,0 +1,101 @@
#ifndef _ARP_H
#define _ARP_H
#include "arp.pb.h"
#include "ui_arp.h"
#include "abstractprotocol.h"
/*
Arp Protocol Frame Format -
+------+------+------+------+------+---------+-------+---------+-------+
| HTYP | PTYP | HLEN | PLEN | OPER | SHA | SPA | THA | TPA |
| (2) | (2) | (1) | (1) | (2) | (6) | (4) | (6) | (4) |
+------+------+------+------+------+---------+-------+---------+-------+
Figures in brackets represent field width in bytes
*/
class ArpConfigForm : public QWidget, public Ui::Arp
{
Q_OBJECT
public:
ArpConfigForm(QWidget *parent = 0);
private slots:
void on_senderHwAddrMode_currentIndexChanged(int index);
void on_senderProtoAddrMode_currentIndexChanged(int index);
void on_targetHwAddrMode_currentIndexChanged(int index);
void on_targetProtoAddrMode_currentIndexChanged(int index);
};
class ArpProtocol : public AbstractProtocol
{
private:
OstProto::Arp data;
ArpConfigForm *configForm;
enum arpfield
{
// Frame Fields
arp_hwType,
arp_protoType,
arp_hwAddrLen,
arp_protoAddrLen,
arp_opCode,
arp_senderHwAddr,
arp_senderProtoAddr,
arp_targetHwAddr,
arp_targetProtoAddr,
// Meta Fields
arp_senderHwAddrMode,
arp_senderHwAddrCount,
arp_senderProtoAddrMode,
arp_senderProtoAddrCount,
arp_senderProtoAddrMask,
arp_targetHwAddrMode,
arp_targetHwAddrCount,
arp_targetProtoAddrMode,
arp_targetProtoAddrCount,
arp_targetProtoAddrMask,
arp_fieldCount
};
public:
ArpProtocol(StreamBase *stream, AbstractProtocol *parent = 0);
virtual ~ArpProtocol();
static AbstractProtocol* createInstance(StreamBase *stream,
AbstractProtocol *parent = 0);
virtual quint32 protocolNumber() const;
virtual void protoDataCopyInto(OstProto::Protocol &protocol) const;
virtual void protoDataCopyFrom(const OstProto::Protocol &protocol);
virtual quint32 protocolId(ProtocolIdType type) const;
virtual QString name() const;
virtual QString shortName() const;
virtual int fieldCount() const;
virtual AbstractProtocol::FieldFlags fieldFlags(int index) const;
virtual QVariant fieldData(int index, FieldAttrib attrib,
int streamIndex = 0) const;
virtual bool setFieldData(int index, const QVariant &value,
FieldAttrib attrib = FieldValue);
virtual bool isProtocolFrameValueVariable() const;
virtual QWidget* configWidget();
virtual void loadConfigWidget();
virtual void storeConfigWidget();
};
#endif

48
common/arp.proto Normal file
View File

@ -0,0 +1,48 @@
import "protocol.proto";
package OstProto;
// ARP Protocol
message Arp {
enum HwAddrMode {
kFixed = 0;
kIncrement = 1;
kDecrement = 2;
}
enum ProtoAddrMode {
kFixedHost = 0;
kIncrementHost = 1;
kDecrementHost = 2;
kRandomHost = 3;
}
optional uint32 hw_type = 1 [default = 1];
optional uint32 proto_type = 2 [default = 0x800];
optional uint32 hw_addr_len = 3 [default = 6];
optional uint32 proto_addr_len = 4 [default = 4];
optional uint32 op_code = 5 [default = 1]; // 1 => ARP Request
optional uint64 sender_hw_addr = 6;
optional HwAddrMode sender_hw_addr_mode = 7 [default = kFixed];
optional uint32 sender_hw_addr_count = 8 [default = 16];
optional uint32 sender_proto_addr = 9;
optional ProtoAddrMode sender_proto_addr_mode = 10 [default = kFixedHost];
optional uint32 sender_proto_addr_count = 11 [default = 16];
optional fixed32 sender_proto_addr_mask = 12 [default = 0xFFFFFF00];
optional uint64 target_hw_addr = 13;
optional HwAddrMode target_hw_addr_mode = 14 [default = kFixed];
optional uint32 target_hw_addr_count = 15 [default = 16];
optional uint32 target_proto_addr = 16;
optional ProtoAddrMode target_proto_addr_mode = 17 [default = kFixedHost];
optional uint32 target_proto_addr_count = 18 [default = 16];
optional fixed32 target_proto_addr_mask = 19 [default = 0xFFFFFF00];
}
extend Protocol {
optional Arp arp = 131;
}

518
common/arp.ui Normal file
View File

@ -0,0 +1,518 @@
<ui version="4.0" >
<class>Arp</class>
<widget class="QWidget" name="Arp" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>528</width>
<height>286</height>
</rect>
</property>
<property name="windowTitle" >
<string>Form</string>
</property>
<layout class="QVBoxLayout" >
<item>
<widget class="QGroupBox" name="groupBox" >
<property name="title" >
<string/>
</property>
<layout class="QGridLayout" >
<item row="0" column="0" >
<widget class="QLabel" name="label" >
<property name="text" >
<string>Hardware Type</string>
</property>
<property name="buddy" >
<cstring>hwType</cstring>
</property>
</widget>
</item>
<item row="0" column="1" >
<widget class="QLineEdit" name="hwType" >
<property name="enabled" >
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="2" >
<widget class="QLabel" name="label_3" >
<property name="text" >
<string>Hardware Address Length</string>
</property>
<property name="buddy" >
<cstring>hwAddrLen</cstring>
</property>
</widget>
</item>
<item row="0" column="3" >
<widget class="QLineEdit" name="hwAddrLen" >
<property name="enabled" >
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="0" >
<widget class="QLabel" name="label_2" >
<property name="text" >
<string>Protocol Type</string>
</property>
<property name="buddy" >
<cstring>protoType</cstring>
</property>
</widget>
</item>
<item row="1" column="1" >
<widget class="QLineEdit" name="protoType" >
<property name="enabled" >
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="2" >
<widget class="QLabel" name="label_4" >
<property name="text" >
<string>Protocol Address Length</string>
</property>
<property name="buddy" >
<cstring>protoAddrLen</cstring>
</property>
</widget>
</item>
<item row="1" column="3" >
<widget class="QLineEdit" name="protoAddrLen" >
<property name="enabled" >
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2" >
<property name="title" >
<string/>
</property>
<layout class="QHBoxLayout" >
<item>
<widget class="QLabel" name="label_6" >
<property name="text" >
<string>Operation Code</string>
</property>
</widget>
</item>
<item>
<widget class="IntComboBox" name="opCodeCombo" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editable" >
<bool>true</bool>
</property>
<property name="insertPolicy" >
<enum>QComboBox::NoInsert</enum>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>161</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_7" >
<property name="title" >
<string/>
</property>
<property name="flat" >
<bool>false</bool>
</property>
<layout class="QGridLayout" >
<item row="0" column="0" >
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>101</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1" >
<widget class="QLabel" name="label_32" >
<property name="text" >
<string>Address</string>
</property>
</widget>
</item>
<item row="0" column="2" >
<widget class="QLabel" name="label_31" >
<property name="text" >
<string>Mode</string>
</property>
</widget>
</item>
<item row="0" column="3" >
<widget class="QLabel" name="label_23" >
<property name="text" >
<string>Count</string>
</property>
</widget>
</item>
<item row="0" column="4" >
<widget class="QLabel" name="label_30" >
<property name="text" >
<string>Mask</string>
</property>
</widget>
</item>
<item row="1" column="0" >
<widget class="QLabel" name="label_7" >
<property name="text" >
<string>Sender Hardware</string>
</property>
<property name="buddy" >
<cstring>senderHwAddr</cstring>
</property>
</widget>
</item>
<item row="1" column="1" >
<widget class="QLineEdit" name="senderHwAddr" >
<property name="inputMask" >
<string>>HH HH HH HH HH HH; </string>
</property>
<property name="text" >
<string> </string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="2" >
<widget class="QComboBox" name="senderHwAddrMode" >
<item>
<property name="text" >
<string>Fixed</string>
</property>
</item>
<item>
<property name="text" >
<string>Increment</string>
</property>
</item>
<item>
<property name="text" >
<string>Decrement</string>
</property>
</item>
</widget>
</item>
<item row="1" column="3" >
<widget class="QLineEdit" name="senderHwAddrCount" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<horstretch>255</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text" >
<string/>
</property>
</widget>
</item>
<item row="2" column="0" >
<widget class="QLabel" name="label_20" >
<property name="text" >
<string>Sender Protocol</string>
</property>
<property name="buddy" >
<cstring>senderProtoAddr</cstring>
</property>
</widget>
</item>
<item row="2" column="1" >
<widget class="QLineEdit" name="senderProtoAddr" >
<property name="inputMask" >
<string>009.009.009.009; </string>
</property>
<property name="text" >
<string>...</string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="2" >
<widget class="QComboBox" name="senderProtoAddrMode" >
<item>
<property name="text" >
<string>Fixed</string>
</property>
</item>
<item>
<property name="text" >
<string>Increment Host</string>
</property>
</item>
<item>
<property name="text" >
<string>Decrement Host</string>
</property>
</item>
<item>
<property name="text" >
<string>Random Host</string>
</property>
</item>
</widget>
</item>
<item row="2" column="3" >
<widget class="QLineEdit" name="senderProtoAddrCount" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<horstretch>255</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text" >
<string/>
</property>
</widget>
</item>
<item row="2" column="4" >
<widget class="QLineEdit" name="senderProtoAddrMask" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="inputMask" >
<string>009.009.009.009; </string>
</property>
<property name="text" >
<string>...</string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="0" >
<widget class="QLabel" name="label_5" >
<property name="text" >
<string>Target Hardware</string>
</property>
<property name="buddy" >
<cstring>targetHwAddr</cstring>
</property>
</widget>
</item>
<item row="3" column="1" >
<widget class="QLineEdit" name="targetHwAddr" >
<property name="minimumSize" >
<size>
<width>120</width>
<height>0</height>
</size>
</property>
<property name="inputMask" >
<string>>HH HH HH HH HH HH; </string>
</property>
<property name="text" >
<string> </string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="2" >
<widget class="QComboBox" name="targetHwAddrMode" >
<item>
<property name="text" >
<string>Fixed</string>
</property>
</item>
<item>
<property name="text" >
<string>Increment</string>
</property>
</item>
<item>
<property name="text" >
<string>Decrement</string>
</property>
</item>
</widget>
</item>
<item row="3" column="3" >
<widget class="QLineEdit" name="targetHwAddrCount" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<horstretch>255</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text" >
<string/>
</property>
<property name="cursorPosition" >
<number>0</number>
</property>
</widget>
</item>
<item row="4" column="0" >
<widget class="QLabel" name="label_21" >
<property name="text" >
<string>Target Protocol</string>
</property>
<property name="buddy" >
<cstring>targetProtoAddr</cstring>
</property>
</widget>
</item>
<item row="4" column="1" >
<widget class="QLineEdit" name="targetProtoAddr" >
<property name="inputMask" >
<string>000.000.000.000; </string>
</property>
<property name="text" >
<string>...</string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="4" column="2" >
<widget class="QComboBox" name="targetProtoAddrMode" >
<item>
<property name="text" >
<string>Fixed</string>
</property>
</item>
<item>
<property name="text" >
<string>Increment Host</string>
</property>
</item>
<item>
<property name="text" >
<string>Decrement Host</string>
</property>
</item>
<item>
<property name="text" >
<string>Random Host</string>
</property>
</item>
</widget>
</item>
<item row="4" column="3" >
<widget class="QLineEdit" name="targetProtoAddrCount" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<horstretch>255</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text" >
<string/>
</property>
</widget>
</item>
<item row="4" column="4" >
<widget class="QLineEdit" name="targetProtoAddrMask" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="inputMask" >
<string>009.009.009.009; </string>
</property>
<property name="text" >
<string>...</string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>61</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>IntComboBox</class>
<extends>QComboBox</extends>
<header>intcombobox.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>hwType</tabstop>
<tabstop>protoType</tabstop>
<tabstop>hwAddrLen</tabstop>
<tabstop>protoAddrLen</tabstop>
<tabstop>senderHwAddr</tabstop>
<tabstop>senderHwAddrMode</tabstop>
<tabstop>senderHwAddrCount</tabstop>
<tabstop>senderProtoAddr</tabstop>
<tabstop>senderProtoAddrMode</tabstop>
<tabstop>senderProtoAddrCount</tabstop>
<tabstop>senderProtoAddrMask</tabstop>
<tabstop>targetHwAddr</tabstop>
<tabstop>targetHwAddrMode</tabstop>
<tabstop>targetHwAddrCount</tabstop>
<tabstop>targetProtoAddr</tabstop>
<tabstop>targetProtoAddrMode</tabstop>
<tabstop>targetProtoAddrCount</tabstop>
<tabstop>targetProtoAddrMask</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

31
common/intcombobox.h Normal file
View File

@ -0,0 +1,31 @@
#include <QComboBox>
class IntComboBox : public QComboBox
{
public:
IntComboBox(QWidget *parent = 0)
: QComboBox(parent)
{
}
void addItem(int value, const QString &text)
{
QComboBox::addItem(QString("%1 - %2").arg(value).arg(text), value);
}
int currentValue()
{
bool isOk;
int index = findText(currentText());
if (index >= 0)
return itemData(index).toInt();
else
return currentText().toInt(&isOk, 0);
}
void setValue(int value)
{
int index = findData(value);
if (index >= 0)
setCurrentIndex(index);
else
setEditText(QString().setNum(value));
}
};

View File

@ -11,6 +11,7 @@ FORMS += \
llc.ui \
snap.ui \
vlan.ui \
arp.ui \
ip4.ui \
tcp.ui \
udp.ui \
@ -29,6 +30,7 @@ PROTOS += \
vlan.proto \
svlan.proto \
vlanstack.proto \
arp.proto \
ip4.proto \
tcp.proto \
udp.proto \
@ -52,6 +54,7 @@ HEADERS += \
vlan.h \
svlan.h \
vlanstack.h \
arp.h \
ip4.h \
tcp.h \
udp.h \
@ -71,6 +74,7 @@ SOURCES += \
snap.cpp \
vlan.cpp \
svlan.cpp \
arp.cpp \
ip4.cpp \
tcp.cpp \
udp.cpp \

View File

@ -12,6 +12,7 @@
#include "dot2snap.h"
#include "vlan.h"
#include "vlanstack.h"
#include "arp.h"
#include "ip4.h"
#include "tcp.h"
#include "udp.h"
@ -28,36 +29,38 @@ ProtocolManager::ProtocolManager()
registerProtocol(OstProto::Protocol::kMacFieldNumber,
(void*) MacProtocol::createInstance);
registerProtocol(OstProto::Protocol::kPayloadFieldNumber,
(void*) PayloadProtocol::createInstance);
(void*) PayloadProtocol::createInstance);
registerProtocol(OstProto::Protocol::kEth2FieldNumber,
(void*) Eth2Protocol::createInstance);
(void*) Eth2Protocol::createInstance);
registerProtocol(OstProto::Protocol::kDot3FieldNumber,
(void*) Dot3Protocol::createInstance);
(void*) Dot3Protocol::createInstance);
registerProtocol(OstProto::Protocol::kLlcFieldNumber,
(void*) LlcProtocol::createInstance);
(void*) LlcProtocol::createInstance);
registerProtocol(OstProto::Protocol::kSnapFieldNumber,
(void*) SnapProtocol::createInstance);
(void*) SnapProtocol::createInstance);
registerProtocol(OstProto::Protocol::kDot2LlcFieldNumber,
(void*) Dot2LlcProtocol::createInstance);
registerProtocol(OstProto::Protocol::kDot2SnapFieldNumber,
(void*) Dot2SnapProtocol::createInstance);
registerProtocol(OstProto::Protocol::kSvlanFieldNumber,
(void*) SVlanProtocol::createInstance);
(void*) SVlanProtocol::createInstance);
registerProtocol(OstProto::Protocol::kVlanFieldNumber,
(void*) VlanProtocol::createInstance);
(void*) VlanProtocol::createInstance);
registerProtocol(OstProto::Protocol::kVlanStackFieldNumber,
(void*) VlanStackProtocol::createInstance);
registerProtocol(OstProto::Protocol::kArpFieldNumber,
(void*) ArpProtocol::createInstance);
registerProtocol(OstProto::Protocol::kIp4FieldNumber,
(void*) Ip4Protocol::createInstance);
(void*) Ip4Protocol::createInstance);
registerProtocol(OstProto::Protocol::kTcpFieldNumber,
(void*) TcpProtocol::createInstance);
(void*) TcpProtocol::createInstance);
registerProtocol(OstProto::Protocol::kUdpFieldNumber,
(void*) UdpProtocol::createInstance);
(void*) UdpProtocol::createInstance);
registerProtocol(OstProto::Protocol::kUserScriptFieldNumber,
(void*) UserScriptProtocol::createInstance);
(void*) UserScriptProtocol::createInstance);
registerProtocol(OstProto::Protocol::kSampleFieldNumber,
(void*) SampleProtocol::createInstance);
(void*) SampleProtocol::createInstance);
populateNeighbourProtocols();
}

View File

@ -84,7 +84,7 @@ quint32 SampleProtocol::protocolId(ProtocolIdType type) const
return AbstractProtocol::protocolId(type);
}
int SampleProtocol::fieldCount() const
int SampleProtocol::fieldCount() const
{
return sample_fieldCount;
}

View File

@ -1,11 +1,11 @@
#ifndef _SAMPLE_H
#define _SAMPLE_H
#include "abstractprotocol.h"
#include "sample.pb.h"
#include "ui_sample.h"
#include "abstractprotocol.h"
/*
Sample Protocol Frame Format -
+-----+------+------+------+------+------+
@ -61,7 +61,7 @@ public:
virtual QString name() const;
virtual QString shortName() const;
virtual int fieldCount() const;
virtual int fieldCount() const;
virtual AbstractProtocol::FieldFlags fieldFlags(int index) const;
virtual QVariant fieldData(int index, FieldAttrib attrib,