Is there a way to sniff/listen an unicast packet/message on Omnet? - omnet++

I am doing development for WSN in Omnet. I want to sniff a unicast message but I don't have an idea how can i do it in Omnet. I made some research but i couldn't found any method for that
When I send data to another node, I am sending it as an unicast with this method :
cModule *nodeIndex = flatTopolojiModulu->getSubmodule("n", i);//n is array
sendDirect(new cMessage("msg"), nodeIndex, "in");
I am using sendDirect method because I am working on wireless network. According to this description : https://stackoverflow.com/a/36082721/5736731
sendDirect method is usually the case in wireless networks.
But when send message with sendDirect, a message is being handled by receiver node. For example, according to code example above:
if i=2, message that is sent only can handle by node which has index "2" from
void AnyClassName::handleMessage(cMessage *msg) function

An example of broadcasting messages can be found in OMNeT++ Manual.
You should create only one instance of message that all nodes have to receive, and then send a new copy of this message to each node in loop. The dup() method has to be used to create the copy of a message.
cMessage * msg = new cMessage("msg");
// totalN is the total number of nodes
for (int i = 0; i < totalN; ++i) {
cModule *nodeIndex = flatTopolojiModulu->getSubmodule("n", i);
sendDirect(msg->dup(), nodeIndex, "in");
}
// original message is no longer needed
delete msg;

Related

I get an error when trying to send to multiple modules using sendDirect

I have to send the same message to multiple modules. I used the following code:
cMessage *msg=new cMessage("Broadcast");
msg->setKind(SENDTOALL);
cTopology topo;
topo.extractByModulePath(cStringTokenizer("**.router*.app[0]").asVector());
cTopology::Node *thisNode = topo.getNodeFor(this);
for (int i = 0; i < topo.getNumNodes(); i++) {
if (topo.getNode(i) == thisNode) continue; // skip ourselves
cModule *targetModule =topo.getNode(i)->getModule();
EV_INFO << "Get Full Name ------------------- "<<i<< topo.getNode(i)->getModule()->getFullPath()<<endl;
sendDirect(msg,targetModule,"in");
after sending the message to the first module and trying to send to the next module, I get the following error that the message already scheduled and the simulation stops at this point.
Can I get any advice? I will be really thankful.
Thank you in advance.
The message cannot be sent more than once. To send the same message to many modules, every time copy of this message must be created. dup() is the convenient method to make a copy, for example:
cMessage *copyMsg = msg->dup();
sendDirect(copyMsg ,targetModule,"in");
Reference: Simulation Manual - Broadcasting messages

error while sending a message from aodvRouter to adhocHost using veins_inet

I'm using inet and veins_inet to simulate vanet. I wanted my nodes to use Aodv to route packets when a packet is sent from one node to another or from one node to rsu to achieve this I did the following :
I declared nodes as aodvRouters and set their mobility to VeinsInetMobility:
*.node[*].typename = "AodvRouter"
*.node[*].mobility.typename = "VeinsInetMobility"
and rsu as AdhocHost with stationary mobility
*.rsu.typename = "AdhocHost"
*.rsu.mobility.typename = "StationaryMobility":
when I use the following code to send a message from a node[43] to node[101] or other nodes it works :
bool nodeApp::startApplication(){
if (getParentModule()->getIndex() == 43) {
destAddress = L3AddressResolver().addressOf(getModuleByPath("node[101]"),27);
auto tipChunk = makeShared<tip>();
timestampPayload(tipChunk);
tipChunk->setChunkLength(B(100));
tipChunk->setPacket_type("tip");
auto packet = createPacket("tip");
packet->insertAtBack(tipChunk);
socket.sendTo(packet.release(), destAddress, 9001);
}
return true;
}
but when I change the dest address to the rsu address it doesn't work I get the following error :
A runtime error occurred:
handlePacket(): Unknown protocol: id = 55, name = nexthopforwarding -- in module (inet::MessageDispatcher) Network.node[34].tn (id=3241), at t=20.000076211898s, event #1103
to solve this error I added the following tag
auto req = packet->addTagIfAbsent<DispatchProtocolReq>();
req->setProtocol(&Protocol::udp);
auto packetProtocolTag = packet->addTagIfAbsent<PacketProtocolTag>();
packetProtocolTag->setProtocol(&Protocol::udp
but I have the followwing error
A runtime error occurred:
Implicit chunk serialization is disabled to prevent unpredictable performance degradation (you may consider changing the Chunk::enableImplicitChunkSerialization flag or passing the PF_ALLOW_SERIALIZATION flag to peek) -- in module (inet::Udp) Network.node[12].udp (id=1216), at t=2.000076936898s, event #378
can anyone help me to send a message from a node to the rsu without broadcasting the packet

Is There way to find the queue is empty using rabbit-template

I have subscriber which collects the messages until reaches the specified limit and then pass collected messages to the processor to perform some operations. Code works fine, problem is subscriber waits Until it collects specified number messages. If we have lesser message program control will not pass to processor.
For example Lets say my chunk size is 100 and if I have 100 or multiple of 100 messages then program works fine But if I have messages < 100 or 150 some of messages are read by subscriber but they were never passed to processor. Is there way I can figure-out is that Queue is empty using rabbit template so that I can check that condition and break the loop
#RabbitListener(id="messageListener",queues = "#{rabbitMqConfig.getSubscriberQueueName()}",containerFactory="queueListenerContainer")
public void receiveMessage(Message message, Channel channel, #Header("id") String messageId,
#Header("amqp_deliveryTag") Long deliveryTag) {
LOGGER.info(" Message:"+ message.toString());
if(messageList.size() < appConfig.getSubscriberChunkSize() ) {
messageList.add(message);
deliveryTagList.add(deliveryTag);
if(messageList.size() == appConfig.getSubscriberChunkSize()) {
LOGGER.info("------------- Calling Message processor --------------");
Message [] messageArry = new Message[messageList.size()];
messageArry = messageList.toArray(messageArry);
LOGGER.info("message Array Length: "+messageArry.length);
messageProcessor.process(messageArry);
messageList = new ArrayList<Message>(Arrays.asList(messageArry));
LOGGER.info("message Array to List conversion Size: "+messageList.size());
LOGGER.info("-------------- Completed Message processor -----------");
eppQ2Publisher.sendMessages(messageList, channel, deliveryTagList);
messageList.clear();
deliveryTagList.clear();
}
} else {
// do nothing..
}
There are two ways to achieve this.
Add an #EventListener to listen for ListenerContainerIdleEvents which are published when no messages have been received for some time; set the container's idleEventInterval property. The source of the event is the listener container; it contains the #RabbitListener's id. See Detecting Idle Consumers.
Use RabbitAdmin.getQueueProperties().
You can use RabbitAdmin.getQueueInfo("queue name").getMessageCount() that will be 0 for empty queue.

Send message only once instead of periodically

I have developed a scenario where at first the vehicles send a self messsage and upon reception of the self message vehicles send a message to RSU.
The self message code is written in the initialize() method. But during simulation the vehicles send the message to RSU every second.
I want the message to be sent only once. What should I do?
I have attached the handleSelfmessage method of my TraCIDemo11p.cc class.
if(msg->isSelfMessage()==true)
{
cModule *tmpMobility = getParentModule()->getSubmodule("veinsmobility");
mobility = dynamic_cast<Veins::TraCIMobility*>(tmpMobility);
ASSERT(mobility);
t_channel channel = dataOnSch ? type_SCH : type_CCH;
WaveShortMessage* wsm = prepareWSM("data", dataLengthBits, channel, dataPriority, -1,2);
wsm->setSenderAddress(myAddress);
wsm->setRecipientAddress(1001);
sendMessage(wsm->getWsmData());
}
Your approach seems right, but obviously you have some problem in your implementation.
Alternatively you can create a new message and send it to yourself
myOneTimeMsg = new cMessage("OneTimeMsg");
scheduleAt(simTime()+1.0, myOneTimeMsg); // this will send the message at t=currentTime+1.0 seconds
Then you can handle that message as follows:
if(msg->isSelfMessage()==true){
if (msg == myOneTimeMsg) {
// do what you need next...
Amending the answer of #user4786271:
The handleSelfMsg method of TraCIDemo11p.cc obviously is executed for every self-message which this module receives - possibly also non WSMs. So if you just added the given code there, it will send a WSM for every of those self-messages. Thus, only checking for self-message type is not enough. You need to create a new message type and check for that type as shown by #user4786271.

How does send() work in omnet++

Does the send() in omnet++ set the source address of the packet to the current host address?
Why am I asking? because I'm trying to code a class for a malicious host "Eve" that performs a replay attack.
void MalAODVRouter::handleMessage(cMessage *msg)
{
cMessage *ReplayMsg = msg->dup();
AODVRouting::handleMessage(msg);
capturedMsgs++;
if (capturedMsgs==10) // One out of every 10 packets (frequency of replay)
{
//we can add a delay before sending the copy of the message again (1 time unit)
sendDelayed(ReplayMsg, 1,"ipOut");
ReplayedMsgs++;
std::cout<<"Launched Replay Packet!\n";
ev<<"Launched Replay Packet!\n";
this->capturedMsgs=0;
// }
}
}
You can see at the beginning of my code snippet I tried using the function dup() to duplicate a packet (msg) Eve's receives while its on it's on its way to the legitimate destination.
Now, can I send the duplicated packet later and it would be having the original source address OR should I dig deeper into layers to fake the source address to have Bob's address instead of Eve's? like below:
/*UDPPacket *udpPacket = dynamic_cast<UDPPacket *>(msg);
AODVControlPacket *ctrlPacket = check_and_cast<AODVControlPacket *>(udpPacket->decapsulate());
IPv4ControlInfo *udpProtocolCtrlInfo = dynamic_cast<IPv4ControlInfo *>(udpPacket->getControlInfo());
ASSERT(udpProtocolCtrlInfo != NULL);
IPv4Address sourceAddr = udpProtocolCtrlInfo->getSrcAddr(); //get Source Address
IPv4Address destinationAddr = udpProtocolCtrlInfo->getDestAddr(); //get Destination Address
IPv4Address addr = getSelfIPAddress();
if (addr != destinationAddr) // if it is not destined for "Eve"
{
UDPPacket *ReplayUDPPacket = udpPacket;
AODVControlPacket *ReplayCtrlPacket = check_and_cast<AODVControlPacket *>(ReplayUDPPacket->decapsulate());
IPv4ControlInfo *ReplayUDPProtocolCtrlInfo = dynamic_cast<IPv4ControlInfo *>(ReplayUDPPacket->getControlInfo());
ASSERT(ReplayUDPProtocolCtrlInfo != NULL);
ReplayUDPProtocolCtrlInfo->setSrcAddr(sourceAddr); //Forge Source
ReplayUDPProtocolCtrlInfo->setDestAddr(destinationAddr); //Keep Destination
*/
//we can add a delay before sending the copy of the message again (1 time unit)
sendDelayed(ReplayMsg, 1,"ipOut");
ReplayedMsgs++;
std::cout<<"Launched Replay Packet!\n";
ev<<"Launched Replay Packet!\n";
this->capturedMsgs=0;
Does the send() method automatically sets the source address of the outgoing packet to the current host address? If so, then my replay attempt is not working...
send() is an OMNeT++ API call. As OMNeT++ is just a generic discrete event simulation framework, it does not know anything about the model code (so it cannot and should not manipulate it). IP address is a defined in the INET framework so only code from the INET framework can change it.
On the other hand the modules in the standard host below you module can do whatever they want before the packet is sent out to the network. Now in this actual case, the source IP address is determined by the control info that is attached to the packet. dup()-ing the packet copies that information too, so the IP address will be the same.

Resources