diff --git a/Scripts/install-build-manet-rank-sim.sh b/Scripts/install-build-manet-rank-sim.sh new file mode 100644 index 0000000000000000000000000000000000000000..a3d0d2050bef73101a04376d4f8a8600604451c0 --- /dev/null +++ b/Scripts/install-build-manet-rank-sim.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# enable specific modules and a pre-built python environment. +module load gcc/8.5.0 +module load cmake/3.25.2 + +## clean, configure and build +#!/bin/bash + +# Check if the argument is provided +if [ -z "$1" ]; then + echo "Please provide an argument." + exit 1 +fi + +# Assign the argument to a variable +input="$1" + +# Test the input and execute code accordingly +if [ "$input" == "clean-debug" ]; then + ./ns3 clean + ./ns3 configure --build-profile=debug --out=build/debug + ./ns3 build + cp build/debug/scratch/manet-rank/MainExperiment/ns3.36.1-manet-routing-debug manet-rank/build/v1_dbg + cd manet-rank/build/ || exit + chmod +x v1_dbg + +elif [ "$input" == "clean-opt" ]; then + ./ns3 clean + ./ns3 configure --build-profile=optimized --out=build/optimized + ./ns3 build + cp build/optimized/scratch/manet-rank-scratch/MainExperiment/ns3.36.1-manet-routing-optimized manet-rank/build/v1_opt + cd manet-rank/build/ || exit + chmod +x v1_opt + +elif [ "$input" == "build-debug" ]; then + ./ns3 build + cp build/debug/scratch/manet-rank-scratch/MainExperiment/ns3.36.1-manet-routing-debug manet-rank/build/v1_dbg + cd manet-rank/build/ || exit + chmod +x v1_dbg + +elif [ "$input" == "build-opt" ]; then + ./ns3 build + cp build/optimized/scratch/manet-rank-scratch/MainExperiment/ns3.36.1-manet-routing-optimized manet-rank/build/v1_opt + cd manet-rank/build/ || exit + chmod +x v1_opt +else + echo "Invalid argument. Please provide a valid option." + exit 1 +fi + +# Add any common code that needs to be executed after the conditionals here + +echo "Script execution complete." \ No newline at end of file diff --git a/build/hpc_template.slurm b/build/hpc_template.slurm new file mode 100644 index 0000000000000000000000000000000000000000..e1a87a19e1a54ecd66154db953e01556bb79ab69 --- /dev/null +++ b/build/hpc_template.slurm @@ -0,0 +1,13 @@ +#!/bin/bash +#SBATCH --nodes=1 +#SBATCH --ntasks=40 +#SBATCH --cpus-per-task=1 +#SBATCH --time=0:30:00 + +module load conda/py3-latest +module load gcc/8.5.0 +module load cmake/3.25.2 + +source activate myenv +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/[USER]/ns3-sims/workspace/ns-allinone-3.36.1/ns-3.36.1/build/optimized/lib: + diff --git a/build/master_template.slurm b/build/master_template.slurm new file mode 100644 index 0000000000000000000000000000000000000000..8ac961825bfbf372c8a59a92102e57ca0660985e --- /dev/null +++ b/build/master_template.slurm @@ -0,0 +1,13 @@ +#!/bin/bash +#SBATCH --nodes=1 +#SBATCH --ntasks=1 +#SBATCH --cpus-per-task=1 +#SBATCH --time=60:00:00 + +module load conda/py3-latest +module load gcc/8.5.0 +module load cmake/3.25.2 + +source activate myenv +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/[USER]/ns3-sims/workspace/ns-allinone-3.36.1/ns-3.36.1/build/optimized/lib: + diff --git a/greyattack-module/CMakeLists.txt b/greyattack-module/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..740a86a6ab7cd9aeed89e4f242c287765e332772 --- /dev/null +++ b/greyattack-module/CMakeLists.txt @@ -0,0 +1,38 @@ +check_include_file_cxx(stdint.h HAVE_STDINT_H) +if(HAVE_STDINT_H) + add_definitions(-DHAVE_STDINT_H) +endif() + +set(examples_as_tests_sources) +if(${ENABLE_EXAMPLES}) + set(examples_as_tests_sources + #test/greyattack-aodv-examples-test-suite.cc + ) +endif() + +build_lib( + LIBNAME greyattack-aodv + SOURCE_FILES model/greyattack-aodv.cc + model/greyattack-aodv-id-cache.cc + model/greyattack-aodv-dpd.cc + model/greyattack-aodv-rtable.cc + model/greyattack-aodv-rqueue.cc + model/greyattack-aodv-packet.cc + model/greyattack-aodv-neighbor.cc + model/greyattack-aodv-routing-protocol.cc + helper/greyattack-aodv-helper.cc + HEADER_FILES model/greyattack-aodv.h + model/greyattack-aodv-id-cache.h + model/greyattack-aodv-dpd.h + model/greyattack-aodv-rtable.h + model/greyattack-aodv-rqueue.h + model/greyattack-aodv-packet.h + model/greyattack-aodv-neighbor.h + model/greyattack-aodv-routing-protocol.h + helper/greyattack-aodv-helper.h + LIBRARIES_TO_LINK ${libinternet} + ${libwifi} + TEST_SOURCES test/greyattack-aodv-test-suite.cc + test/greyattack-aodv-id-cache-test-suite.cc + ${examples_as_tests_sources} +) \ No newline at end of file diff --git a/greyattack-module/doc/greyattack-aodv.h b/greyattack-module/doc/greyattack-aodv.h new file mode 100644 index 0000000000000000000000000000000000000000..b01c12f4874fc1d468d7856ff85a3fe7ded42e5e --- /dev/null +++ b/greyattack-module/doc/greyattack-aodv.h @@ -0,0 +1,38 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based on + * NS-2 aodvKmeans model developed by the CMU/MONARCH group and optimized and + * tuned by Samir Das and Mahesh Marina, University of Cincinnati; + * + * aodvKmeans-UU implementation by Erik Nordström of Uppsala University + * http://core.it.uu.se/core/index.php/aodvKmeans-UU + * + * Authors: Elena Buchatskaia <borovkovaes@iitp.ru> + * Pavel Boyko <boyko@iitp.ru> + */ + +#ifndef greyattack_aodv_H +#define greyattack_aodv_H + +/** + * \defgroup aodvKmeans aodvKmeans Routing + * + * This section documents the API of the ns-3 aodvKmeans module. For a generic functional description, please refer to the ns-3 manual. + */ + +#endif /* greyattack_aodv_H */ diff --git a/greyattack-module/doc/greyattack-aodv.rst b/greyattack-module/doc/greyattack-aodv.rst new file mode 100644 index 0000000000000000000000000000000000000000..837100bbab433409b8350e02f1af88993af7ef16 --- /dev/null +++ b/greyattack-module/doc/greyattack-aodv.rst @@ -0,0 +1,135 @@ +.. include:: replace.txt + +Ad Hoc On-Demand Distance Vector (aodvKmeans) +--------------------------------------- + +This model implements the base specification of the Ad Hoc On-Demand +Distance Vector (aodvKmeans) protocol. The implementation is based on +:rfc:`3561`. + +The model was written by Elena Buchatskaia and Pavel Boyko of ITTP RAS, +and is based on the ns-2 aodvKmeans model developed by the CMU/MONARCH group +and optimized and tuned by Samir Das and Mahesh Marina, University of +Cincinnati, and also on the aodvKmeans-UU implementation by Erik Nordström of +Uppsala University. + +Model Description +***************** + +The source code for the aodvKmeans model lives in the directory `src/aodvKmeans`. + +Design +++++++ + +Class ``ns3::aodvKmeans::RoutingProtocol`` implements all functionality of +service packet exchange and inherits from ``ns3::Ipv4RoutingProtocol``. +The base class defines two virtual functions for packet routing and +forwarding. The first one, ``ns3::aodvKmeans::RouteOutput``, is used for +locally originated packets, and the second one, ``ns3::aodvKmeans::RouteInput``, +is used for forwarding and/or delivering received packets. + +Protocol operation depends on many adjustable parameters. Parameters for +this functionality are attributes of ``ns3::aodvKmeans::RoutingProtocol``. +Parameter default values are drawn from the RFC and allow the +enabling/disabling protocol features, such as broadcasting HELLO messages, +broadcasting data packets and so on. + +aodvKmeans discovers routes on demand. Therefore, the aodvKmeans model buffers all +packets while a route request packet (RREQ) is disseminated. +A packet queue is implemented in aodvKmeans-rqueue.cc. A smart pointer to +the packet, ``ns3::Ipv4RoutingProtocol::ErrorCallback``, +``ns3::Ipv4RoutingProtocol::UnicastForwardCallback``, and the IP header +are stored in this queue. The packet queue implements garbage collection +of old packets and a queue size limit. + +The routing table implementation supports garbage collection of +old entries and state machine, defined in the standard. +It is implemented as a STL map container. The key is a destination IP address. + +Some elements of protocol operation aren't described in the RFC. These +elements generally concern cooperation of different OSI model layers. +The model uses the following heuristics: + +* This aodvKmeans implementation can detect the presence of unidirectional + links and avoid them if necessary. If the node the model receives an + RREQ for is a neighbor, the cause may be a unidirectional link. + This heuristic is taken from aodvKmeans-UU implementation and can be disabled. +* Protocol operation strongly depends on broken link detection mechanism. + The model implements two such heuristics. First, this implementation + support HELLO messages. However HELLO messages are not a good way to + perform neighbor sensing in a wireless environment (at least not over + 802.11). Therefore, one may experience bad performance when running over + wireless. There are several reasons for this: 1) HELLO messages are + broadcasted. In 802.11, broadcasting is often done at a + lower bit rate than unicasting, thus HELLO messages can travel further + than unicast data. 2) HELLO messages are small, thus less prone to + bit errors than data transmissions, and 3) Broadcast transmissions are + not guaranteed to be bidirectional, unlike unicast transmissions. + Second, we use layer 2 feedback when possible. Link are considered to be + broken if frame transmission results in a transmission failure for all + retries. This mechanism is meant for active links and works faster than + the first method. + +The layer 2 feedback implementation relies on the ``TxErrHeader`` trace source, +currently supported in AdhocWifiMac only. + +Scope and Limitations ++++++++++++++++++++++ + +The model is for IPv4 only. The following optional protocol optimizations +are not implemented: + +#. Local link repair. +#. RREP, RREQ and HELLO message extensions. + +These techniques require direct access to IP header, which contradicts +the assertion from the aodvKmeans RFC that aodvKmeans works over UDP. This model uses +UDP for simplicity, hindering the ability to implement certain protocol +optimizations. The model doesn't use low layer raw sockets because they +are not portable. + +Future Work ++++++++++++ + +No announced plans. + +.. + References + ++++++++++ + +.. + Usage + ***** + +.. + Examples + ++++++++ + +.. + Helpers + +++++++ + +.. + Attributes + ++++++++++ + +.. + Tracing + +++++++ + +.. + Logging + +++++++ + +.. + Caveats + +++++++ + +.. + Validation + ********** + Unit tests + ++++++++++ + Larger-scale performance tests + ++++++++++++++++++++++++++++++ + diff --git a/greyattack-module/examples/greyattack-aodv.cc b/greyattack-module/examples/greyattack-aodv.cc new file mode 100644 index 0000000000000000000000000000000000000000..e7f77a608d3f5760eef706540cbc55ae9761eda2 --- /dev/null +++ b/greyattack-module/examples/greyattack-aodv.cc @@ -0,0 +1,243 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This is an example script for greyattack manet routing protocol. + * + * Authors: Pavel Boyko <boyko@iitp.ru> + */ + +#include <iostream> +#include <cmath> +#include "ns3/greydefense-aodv-module.h" +#include "ns3/core-module.h" +#include "ns3/network-module.h" +#include "ns3/internet-module.h" +#include "ns3/mobility-module.h" +#include "ns3/point-to-point-module.h" +#include "ns3/v4ping-helper.h" +#include "ns3/yans-wifi-helper.h" + +using namespace ns3; + +/** + * \ingroup greyattack-examples + * \ingroup examples + * \brief Test script. + * + * This script creates 1-dimensional grid topology and then ping last node from the first one: + * + * [10.0.0.1] <-- step --> [10.0.0.2] <-- step --> [10.0.0.3] <-- step --> [10.0.0.4] + * + * ping 10.0.0.4 + * + * When 1/3 of simulation time has elapsed, one of the nodes is moved out of + * range, thereby breaking the topology. By default, this will result in + * only 34 of 100 pings being received. If the step size is reduced + * to cover the gap, then all pings can be received. + */ +class greyattackExample +{ +public: + greyattackExample (); + /** + * \brief Configure script parameters + * \param argc is the command line argument count + * \param argv is the command line arguments + * \return true on successful configuration + */ + bool Configure (int argc, char **argv); + /// Run simulation + void Run (); + /** + * Report results + * \param os the output stream + */ + void Report (std::ostream & os); + +private: + + // parameters + /// Number of nodes + uint32_t size; + /// Distance between nodes, meters + double step; + /// Simulation time, seconds + double totalTime; + /// Write per-device PCAP traces if true + bool pcap; + /// Print routes if true + bool printRoutes; + + // network + /// nodes used in the example + NodeContainer nodes; + /// devices used in the example + NetDeviceContainer devices; + /// interfaces used in the example + Ipv4InterfaceContainer interfaces; + +private: + /// Create the nodes + void CreateNodes (); + /// Create the devices + void CreateDevices (); + /// Create the network + void InstallInternetStack (); + /// Create the simulation applications + void InstallApplications (); +}; + +int main (int argc, char **argv) +{ + greyattackExample test; + if (!test.Configure (argc, argv)) + NS_FATAL_ERROR ("Configuration failed. Aborted."); + + test.Run (); + test.Report (std::cout); + return 0; +} + +//----------------------------------------------------------------------------- +greyattackExample::greyattackExample () : + size (10), + step (50), + totalTime (100), + pcap (false), + printRoutes (false) +{ +} + +bool +greyattackExample::Configure (int argc, char **argv) +{ + // Enable greyattack logs by default. Comment this if too noisy + // LogComponentEnable("greyattackRoutingProtocol", LOG_LEVEL_ALL); + + SeedManager::SetSeed (12345); + CommandLine cmd (__FILE__); + + cmd.AddValue ("pcap", "Write PCAP traces.", pcap); + cmd.AddValue ("printRoutes", "Print routing table dumps.", printRoutes); + cmd.AddValue ("size", "Number of nodes.", size); + cmd.AddValue ("time", "Simulation time, s.", totalTime); + cmd.AddValue ("step", "Grid step, m", step); + + cmd.Parse (argc, argv); + return true; +} + +void +greyattackExample::Run () +{ +// Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", UintegerValue (1)); // enable rts cts all the time. + CreateNodes (); + CreateDevices (); + InstallInternetStack (); + InstallApplications (); + + std::cout << "Starting simulation for " << totalTime << " s ...\n"; + + Simulator::Stop (Seconds (totalTime)); + Simulator::Run (); + Simulator::Destroy (); +} + +void +greyattackExample::Report (std::ostream &) +{ +} + +void +greyattackExample::CreateNodes () +{ + std::cout << "Creating " << (unsigned)size << " nodes " << step << " m apart.\n"; + nodes.Create (size); + // Name nodes + for (uint32_t i = 0; i < size; ++i) + { + std::ostringstream os; + os << "node-" << i; + Names::Add (os.str (), nodes.Get (i)); + } + // Create static grid + MobilityHelper mobility; + mobility.SetPositionAllocator ("ns3::GridPositionAllocator", + "MinX", DoubleValue (0.0), + "MinY", DoubleValue (0.0), + "DeltaX", DoubleValue (step), + "DeltaY", DoubleValue (0), + "GridWidth", UintegerValue (size), + "LayoutType", StringValue ("RowFirst")); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (nodes); +} + +void +greyattackExample::CreateDevices () +{ + WifiMacHelper wifiMac; + wifiMac.SetType ("ns3::AdhocWifiMac"); + YansWifiPhyHelper wifiPhy; + YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default (); + wifiPhy.SetChannel (wifiChannel.Create ()); + WifiHelper wifi; + + wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue ("OfdmRate6Mbps"), "RtsCtsThreshold", UintegerValue (0)); + devices = wifi.Install (wifiPhy, wifiMac, nodes); + + if (pcap) + { + wifiPhy.EnablePcapAll (std::string ("greyattack")); + } +} + +void +greyattackExample::InstallInternetStack () +{ + greyattackHelper greyattack; + // you can configure greyattack attributes here using greyattack.Set(name, value) + InternetStackHelper stack; + stack.SetRoutingHelper (greyattack); // has effect on the next Install () + stack.Install (nodes); + Ipv4AddressHelper address; + address.SetBase ("10.0.0.0", "255.0.0.0"); + interfaces = address.Assign (devices); + + if (printRoutes) + { + Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper> ("greyattack.routes", std::ios::out); + greyattack.PrintRoutingTableAllAt (Seconds (8), routingStream); + } +} + +void +greyattackExample::InstallApplications () +{ + V4PingHelper ping (interfaces.GetAddress (size - 1)); + ping.SetAttribute ("Verbose", BooleanValue (true)); + + ApplicationContainer p = ping.Install (nodes.Get (0)); + p.Start (Seconds (0)); + p.Stop (Seconds (totalTime) - Seconds (0.001)); + + // move node away + Ptr<Node> node = nodes.Get (size/2); + Ptr<MobilityModel> mob = node->GetObject<MobilityModel> (); + Simulator::Schedule (Seconds (totalTime/3), &MobilityModel::SetPosition, mob, Vector (1e5, 1e5, 1e5)); +} + diff --git a/greyattack-module/examples/wscript b/greyattack-module/examples/wscript new file mode 100644 index 0000000000000000000000000000000000000000..79178f75e97d65298419342f585972b16531f0ea --- /dev/null +++ b/greyattack-module/examples/wscript @@ -0,0 +1,6 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + +def build(bld): + obj = bld.create_ns3_program('greydefense-aodv', + ['wifi', 'internet', 'greydefense-aodv', 'internet-apps']) + obj.source = 'greydefense-aodv.cc' diff --git a/greyattack-module/helper/greyattack-aodv-helper.cc b/greyattack-module/helper/greyattack-aodv-helper.cc new file mode 100644 index 0000000000000000000000000000000000000000..7c929d2912b149a5bc5c6de77c62aa7375bf27ce --- /dev/null +++ b/greyattack-module/helper/greyattack-aodv-helper.cc @@ -0,0 +1,96 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Pavel Boyko <boyko@iitp.ru>, written after OlsrHelper by Mathieu Lacage <mathieu.lacage@sophia.inria.fr> + */ +#include "greyattack-aodv-helper.h" +#include "ns3/greyattack-aodv-routing-protocol.h" +#include "ns3/node-list.h" +#include "ns3/names.h" +#include "ns3/ptr.h" +#include "ns3/ipv4-list-routing.h" + +namespace ns3 +{ + +greyattackHelper::greyattackHelper() : + Ipv4RoutingHelper () +{ + m_agentFactory.SetTypeId ("ns3::greyattack-aodv::RoutingProtocol"); +} + +greyattackHelper* +greyattackHelper::Copy (void) const +{ + return new greyattackHelper (*this); +} + +Ptr<Ipv4RoutingProtocol> +greyattackHelper::Create (Ptr<Node> node) const +{ + Ptr<greyattackAodv::RoutingProtocol> agent = m_agentFactory.Create<greyattackAodv::RoutingProtocol> (); + node->AggregateObject (agent); + return agent; +} + +void +greyattackHelper::Set (std::string name, const AttributeValue &value) +{ + m_agentFactory.Set (name, value); +} + +int64_t +greyattackHelper::AssignStreams (NodeContainer c, int64_t stream) +{ + int64_t currentStream = stream; + Ptr<Node> node; + for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i) + { + node = (*i); + Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> (); + NS_ASSERT_MSG (ipv4, "Ipv4 not installed on node"); + Ptr<Ipv4RoutingProtocol> proto = ipv4->GetRoutingProtocol (); + NS_ASSERT_MSG (proto, "Ipv4 routing not installed on node"); + Ptr<greyattackAodv::RoutingProtocol> greyattack = DynamicCast<greyattackAodv::RoutingProtocol> (proto); + if (greyattack) + { + currentStream += greyattack->AssignStreams (currentStream); + continue; + } + // greyattack may also be in a list + Ptr<Ipv4ListRouting> list = DynamicCast<Ipv4ListRouting> (proto); + if (list) + { + int16_t priority; + Ptr<Ipv4RoutingProtocol> listProto; + Ptr<greyattackAodv::RoutingProtocol> listgreyattack; + for (uint32_t i = 0; i < list->GetNRoutingProtocols (); i++) + { + listProto = list->GetRoutingProtocol (i, priority); + listgreyattack = DynamicCast<greyattackAodv::RoutingProtocol> (listProto); + if (listgreyattack) + { + currentStream += listgreyattack->AssignStreams (currentStream); + break; + } + } + } + } + return (currentStream - stream); +} + +} diff --git a/greyattack-module/helper/greyattack-aodv-helper.h b/greyattack-module/helper/greyattack-aodv-helper.h new file mode 100644 index 0000000000000000000000000000000000000000..e12f768a83c054550ea4e644e1fa696008f9a318 --- /dev/null +++ b/greyattack-module/helper/greyattack-aodv-helper.h @@ -0,0 +1,84 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Pavel Boyko <boyko@iitp.ru>, written after OlsrHelper by Mathieu Lacage <mathieu.lacage@sophia.inria.fr> + */ + +#ifndef greyattack_aodv_HELPER_H +#define greyattack_aodv_HELPER_H + +#include "ns3/object-factory.h" +#include "ns3/node.h" +#include "ns3/node-container.h" +#include "ns3/ipv4-routing-helper.h" + +namespace ns3 { +/** + * \ingroup greyattack + * \brief Helper class that adds greyattack routing to nodes. + */ +class greyattackHelper : public Ipv4RoutingHelper +{ +public: + greyattackHelper (); + + /** + * \returns pointer to clone of this greyattackHelper + * + * \internal + * This method is mainly for internal use by the other helpers; + * clients are expected to free the dynamic memory allocated by this method + */ + greyattackHelper* Copy (void) const; + + /** + * \param node the node on which the routing protocol will run + * \returns a newly-created routing protocol + * + * This method will be called by ns3::InternetStackHelper::Install + * + * \todo support installing greyattack on the subset of all available IP interfaces + */ + virtual Ptr<Ipv4RoutingProtocol> Create (Ptr<Node> node) const; + /** + * \param name the name of the attribute to set + * \param value the value of the attribute to set. + * + * This method controls the attributes of ns3::greyattack::RoutingProtocol + */ + void Set (std::string name, const AttributeValue &value); + /** + * Assign a fixed random variable stream number to the random variables + * used by this model. Return the number of streams (possibly zero) that + * have been assigned. The Install() method of the InternetStackHelper + * should have previously been called by the user. + * + * \param stream first stream index to use + * \param c NodeContainer of the set of nodes for which greyattack + * should be modified to use a fixed stream + * \return the number of stream indices assigned by this helper + */ + int64_t AssignStreams (NodeContainer c, int64_t stream); + +private: + /** the factory to create greyattack routing object */ + ObjectFactory m_agentFactory; +}; + +} + +#endif /* greyattack_HELPER_H */ diff --git a/greyattack-module/model/greyattack-aodv-dpd.cc b/greyattack-module/model/greyattack-aodv-dpd.cc new file mode 100644 index 0000000000000000000000000000000000000000..744c480aef8f70bb156ba3cb69a9d5d11ec7099f --- /dev/null +++ b/greyattack-module/model/greyattack-aodv-dpd.cc @@ -0,0 +1,48 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * Authors: Elena Buchatskaia <borovkovaes@iitp.ru> + * Pavel Boyko <boyko@iitp.ru> + */ + +#include "greyattack-aodv-dpd.h" + +namespace ns3 { +namespace greyattackAodv { + +bool +DuplicatePacketDetection::IsDuplicate (Ptr<const Packet> p, const Ipv4Header & header) +{ + return m_idCache.IsDuplicate (header.GetSource (), p->GetUid () ); +} +void +DuplicatePacketDetection::SetLifetime (Time lifetime) +{ + m_idCache.SetLifetime (lifetime); +} + +Time +DuplicatePacketDetection::GetLifetime () const +{ + return m_idCache.GetLifeTime (); +} + + +} +} + diff --git a/greyattack-module/model/greyattack-aodv-dpd.h b/greyattack-module/model/greyattack-aodv-dpd.h new file mode 100644 index 0000000000000000000000000000000000000000..c57d59e239f85905d8f0e39111b895c9fbe01806 --- /dev/null +++ b/greyattack-module/model/greyattack-aodv-dpd.h @@ -0,0 +1,76 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * Authors: Elena Buchatskaia <borovkovaes@iitp.ru> + * Pavel Boyko <boyko@iitp.ru> + */ + +#ifndef greyattack_aodv_DPD_H +#define greyattack_aodv_DPD_H + +#include "greyattack-aodv-id-cache.h" +#include "ns3/nstime.h" +#include "ns3/packet.h" +#include "ns3/ipv4-header.h" + +namespace ns3 { +namespace greyattackAodv { +/** + * \ingroup greyattack-aodv + * + * \brief Helper class used to remember already seen packets and detect duplicates. + * + * Currently duplicate detection is based on unique packet ID given by Packet::GetUid () + * This approach is known to be weak (ns3::Packet UID is an internal identifier and not intended for logical uniqueness in models) and should be changed. + */ +class DuplicatePacketDetection +{ +public: + /** + * Constructor + * \param lifetime the lifetime for added entries + */ + DuplicatePacketDetection (Time lifetime) : m_idCache (lifetime) + { + } + /** + * Check if the packet is a duplicate. If not, save information about this packet. + * \param p the packet to check + * \param header the IP header to check + * \returns true if duplicate + */ + bool IsDuplicate (Ptr<const Packet> p, const Ipv4Header & header); + /** + * Set duplicate record lifetime + * \param lifetime the lifetime for duplicate records + */ + void SetLifetime (Time lifetime); + /** + * Get duplicate record lifetime + * \returns the duplicate record lifetime + */ + Time GetLifetime () const; +private: + /// Impl + IdCache m_idCache; +}; + +} +} + +#endif /* greyattack_aodv_DPD_H */ diff --git a/greyattack-module/model/greyattack-aodv-id-cache.cc b/greyattack-module/model/greyattack-aodv-id-cache.cc new file mode 100644 index 0000000000000000000000000000000000000000..5e3d230b452857266ebc26c884519b8bef671136 --- /dev/null +++ b/greyattack-module/model/greyattack-aodv-id-cache.cc @@ -0,0 +1,62 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based on + * NS-3 + * + * Authors: Charles Hutchins + */ +#include "greyattack-aodv-id-cache.h" +#include <algorithm> + +namespace ns3 { +namespace greyattackAodv { +bool +IdCache::IsDuplicate (Ipv4Address addr, uint32_t id) +{ + Purge (); + for (std::vector<UniqueId>::const_iterator i = m_idCache.begin (); + i != m_idCache.end (); ++i) + { + if (i->m_context == addr && i->m_id == id) + { + return true; + } + } + struct UniqueId uniqueId = + { + addr, id, m_lifetime + Simulator::Now () + }; + m_idCache.push_back (uniqueId); + return false; +} +void +IdCache::Purge () +{ + m_idCache.erase (remove_if (m_idCache.begin (), m_idCache.end (), + IsExpired ()), m_idCache.end ()); +} + +uint32_t +IdCache::GetSize () +{ + Purge (); + return m_idCache.size (); +} + +} +} diff --git a/greyattack-module/model/greyattack-aodv-id-cache.h b/greyattack-module/model/greyattack-aodv-id-cache.h new file mode 100644 index 0000000000000000000000000000000000000000..e85b6534ceaedfff34dc9aabb664a2116fcc5d1f --- /dev/null +++ b/greyattack-module/model/greyattack-aodv-id-cache.h @@ -0,0 +1,113 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based on + * NS-3 greyattack model developed by + * + * Authors: Charles Hutchins + */ + +#ifndef greyattack_aodv_ID_CACHE_H +#define greyattack_aodv_ID_CACHE_H + +#include "ns3/ipv4-address.h" +#include "ns3/simulator.h" +#include <vector> + +namespace ns3 { +namespace greyattackAodv { +/** + * \ingroup greyattack + * + * \brief Unique packets identification cache used for simple duplicate detection. + */ +class IdCache +{ +public: + /** + * constructor + * \param lifetime the lifetime for added entries + */ + IdCache (Time lifetime) : m_lifetime (lifetime) + { + } + /** + * Check that entry (addr, id) exists in cache. Add entry, if it doesn't exist. + * \param addr the IP address + * \param id the cache entry ID + * \returns true if the pair exists + */ + bool IsDuplicate (Ipv4Address addr, uint32_t id); + /// Remove all expired entries + void Purge (); + /** + * \returns number of entries in cache + */ + uint32_t GetSize (); + /** + * Set lifetime for future added entries. + * \param lifetime the lifetime for entries + */ + void SetLifetime (Time lifetime) + { + m_lifetime = lifetime; + } + /** + * Return lifetime for existing entries in cache + * \returns thhe lifetime + */ + Time GetLifeTime () const + { + return m_lifetime; + } +private: + /// Unique packet ID + struct UniqueId + { + /// ID is supposed to be unique in single address context (e.g. sender address) + Ipv4Address m_context; + /// The id + uint32_t m_id; + /// When record will expire + Time m_expire; + }; + /** + * \brief IsExpired structure + */ + struct IsExpired + { + /** + * \brief Check if the entry is expired + * + * \param u UniqueId entry + * \return true if expired, false otherwise + */ + bool operator() (const struct UniqueId & u) const + { + return (u.m_expire < Simulator::Now ()); + } + }; + /// Already seen IDs + std::vector<UniqueId> m_idCache; + /// Default lifetime for ID records + Time m_lifetime; +}; + +} // namespace greyattack +} // namespace ns3 + +#endif /* greyattack_aodv_ID_CACHE_H */ diff --git a/greyattack-module/model/greyattack-aodv-neighbor.cc b/greyattack-module/model/greyattack-aodv-neighbor.cc new file mode 100644 index 0000000000000000000000000000000000000000..40cbd7787c91496abc40555ad33c62a0bd53bc59 --- /dev/null +++ b/greyattack-module/model/greyattack-aodv-neighbor.cc @@ -0,0 +1,198 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based on + * NS-3 greyattack model + * + * Authors: Charles Hutchins + */ + +#include <algorithm> +#include "ns3/log.h" +#include "ns3/wifi-mac-header.h" +#include "greyattack-aodv-neighbor.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("greyattack-aodv-Neighbors"); + +namespace greyattackAodv { +Neighbors::Neighbors (Time delay) + : m_ntimer (Timer::CANCEL_ON_DESTROY) +{ + m_ntimer.SetDelay (delay); + m_ntimer.SetFunction (&Neighbors::Purge, this); + m_txErrorCallback = MakeCallback (&Neighbors::ProcessTxError, this); +} + +bool +Neighbors::IsNeighbor (Ipv4Address addr) +{ + Purge (); + for (std::vector<Neighbor>::const_iterator i = m_nb.begin (); + i != m_nb.end (); ++i) + { + if (i->m_neighborAddress == addr) + { + return true; + } + } + return false; +} + +Time +Neighbors::GetExpireTime (Ipv4Address addr) +{ + Purge (); + for (std::vector<Neighbor>::const_iterator i = m_nb.begin (); i + != m_nb.end (); ++i) + { + if (i->m_neighborAddress == addr) + { + return (i->m_expireTime - Simulator::Now ()); + } + } + return Seconds (0); +} + +void +Neighbors::Update (Ipv4Address addr, Time expire) +{ + for (std::vector<Neighbor>::iterator i = m_nb.begin (); i != m_nb.end (); ++i) + { + if (i->m_neighborAddress == addr) + { + i->m_expireTime + = std::max (expire + Simulator::Now (), i->m_expireTime); + if (i->m_hardwareAddress == Mac48Address ()) + { + i->m_hardwareAddress = LookupMacAddress (i->m_neighborAddress); + } + return; + } + } + + NS_LOG_LOGIC ("Open link to " << addr); + Neighbor neighbor (addr, LookupMacAddress (addr), expire + Simulator::Now ()); + m_nb.push_back (neighbor); + Purge (); +} + + + + + + + +/** + * \brief CloseNeighbor structure + */ +struct CloseNeighbor +{ + /** + * Check if the entry is expired + * + * \param nb Neighbors::Neighbor entry + * \return true if expired, false otherwise + */ + bool operator() (const Neighbors::Neighbor & nb) const + { + return ((nb.m_expireTime < Simulator::Now ()) || nb.close); + } +}; + +void +Neighbors::Purge () +{ + if (m_nb.empty ()) + { + return; + } + + CloseNeighbor pred; + if (!m_handleLinkFailure.IsNull ()) + { + for (std::vector<Neighbor>::iterator j = m_nb.begin (); j != m_nb.end (); ++j) + { + if (pred (*j)) + { + NS_LOG_LOGIC ("Close link to " << j->m_neighborAddress); + m_handleLinkFailure (j->m_neighborAddress); + } + } + } + m_nb.erase (std::remove_if (m_nb.begin (), m_nb.end (), pred), m_nb.end ()); + m_ntimer.Cancel (); + m_ntimer.Schedule (); +} + +void +Neighbors::ScheduleTimer () +{ + m_ntimer.Cancel (); + m_ntimer.Schedule (); +} + +void +Neighbors::AddArpCache (Ptr<ArpCache> a) +{ + m_arp.push_back (a); +} + +void +Neighbors::DelArpCache (Ptr<ArpCache> a) +{ + m_arp.erase (std::remove (m_arp.begin (), m_arp.end (), a), m_arp.end ()); +} + +Mac48Address +Neighbors::LookupMacAddress (Ipv4Address addr) +{ + Mac48Address hwaddr; + for (std::vector<Ptr<ArpCache> >::const_iterator i = m_arp.begin (); + i != m_arp.end (); ++i) + { + ArpCache::Entry * entry = (*i)->Lookup (addr); + if (entry != 0 && (entry->IsAlive () || entry->IsPermanent ()) && !entry->IsExpired ()) + { + hwaddr = Mac48Address::ConvertFrom (entry->GetMacAddress ()); + break; + } + } + return hwaddr; +} + + + +void +Neighbors::ProcessTxError (WifiMacHeader const & hdr) +{ + Mac48Address addr = hdr.GetAddr1 (); + + for (std::vector<Neighbor>::iterator i = m_nb.begin (); i != m_nb.end (); ++i) + { + if (i->m_hardwareAddress == addr) + { + i->close = true; + } + } + Purge (); +} + +} // namespace greyattack-aodv +} // namespace ns3 + diff --git a/greyattack-module/model/greyattack-aodv-neighbor.h b/greyattack-module/model/greyattack-aodv-neighbor.h new file mode 100644 index 0000000000000000000000000000000000000000..086a79af274daaf9efe578e8f4d8f94ee200ced6 --- /dev/null +++ b/greyattack-module/model/greyattack-aodv-neighbor.h @@ -0,0 +1,184 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based on + * NS-3 greyattack model developed by + * + * Authors: Charles Hutchins + */ + +#ifndef greyattack_aodvNEIGHBOR_H +#define greyattack_aodvNEIGHBOR_H + +#include <vector> +#include "ns3/simulator.h" +#include "ns3/timer.h" +#include "ns3/ipv4-address.h" +#include "ns3/callback.h" +#include "ns3/arp-cache.h" + +namespace ns3 { + +class WifiMacHeader; + +namespace greyattackAodv { + +class RoutingProtocol; + +/** + * \ingroup greyattack-aodv + * \brief maintain list of active neighbors + */ +class Neighbors +{ +public: + /** + * constructor + * \param delay the delay time for purging the list of neighbors + */ + Neighbors (Time delay); + /// Neighbor description + struct Neighbor + { + /// Neighbor IPv4 address + Ipv4Address m_neighborAddress; + /// Neighbor MAC address + Mac48Address m_hardwareAddress; + /// Neighbor expire time + Time m_expireTime; + /// Neighbor close indicator + bool close; + /// cluster id of neighbour + + /** + * \brief Neighbor structure constructor + * + * \param ip Ipv4Address entry + * \param mac Mac48Address entry + * \param t Time expire time + */ + Neighbor (Ipv4Address ip, Mac48Address mac, Time t) + : m_neighborAddress (ip), + m_hardwareAddress (mac), + m_expireTime (t), + close (false) + + { + } + }; + /** + * Return expire time for neighbor node with address addr, if exists, else return 0. + * \param addr the IP address of the neighbor node + * \returns the expire time for the neighbor node + */ + Time GetExpireTime (Ipv4Address addr); + + /** + * Check that node with address addr is neighbor + * \param addr the IP address to check + * \returns true if the node with IP address is a neighbor + */ + bool IsNeighbor (Ipv4Address addr); + /** + * Update expire time for entry with address addr, if it exists, else add new entry + * \param addr the IP address to check + * \param expire the expire time for the address + */ + void Update (Ipv4Address addr, Time expire); + /// Remove all expired entries + void Purge (); + /// Schedule m_ntimer. + void ScheduleTimer (); + /// Remove all entries + void Clear () + { + m_nb.clear (); + } + + /** + * Add ARP cache to be used to allow layer 2 notifications processing + * \param a pointer to the ARP cache to add + */ + void AddArpCache (Ptr<ArpCache> a); + /** + * Don't use given ARP cache any more (interface is down) + * \param a pointer to the ARP cache to delete + */ + void DelArpCache (Ptr<ArpCache> a); + /** + * Get callback to ProcessTxError + * \returns the callback function + */ + Callback<void, WifiMacHeader const &> GetTxErrorCallback () const + { + return m_txErrorCallback; + } + + /** + * Set link failure callback + * \param cb the callback function + */ + void SetCallback (Callback<void, Ipv4Address> cb) + { + m_handleLinkFailure = cb; + } + /** + * Get link failure callback + * \returns the link failure callback + */ + Callback<void, Ipv4Address> GetCallback () const + { + return m_handleLinkFailure; + } + + + + + +private: + /// link failure callback + Callback<void, Ipv4Address> m_handleLinkFailure; + /// TX error callback + Callback<void, WifiMacHeader const &> m_txErrorCallback; + /// Timer for neighbor's list. Schedule Purge(). + Timer m_ntimer; + /// vector of entries + std::vector<Neighbor> m_nb; + /// list of ARP cached to be used for layer 2 notifications processing + std::vector<Ptr<ArpCache> > m_arp; + + + /** + * Find MAC address by IP using list of ARP caches + * + * \param addr the IP address to lookup + * \returns the MAC address for the IP address + */ + Mac48Address LookupMacAddress (Ipv4Address addr); + /** + * Process layer 2 TX error notification + * \param hdr header of the packet + */ + void ProcessTxError (WifiMacHeader const &hdr); + + +}; + +} // namespace greyattack +} // namespace ns3 + +#endif /* greyattack_aodvNEIGHBOR_H */ diff --git a/greyattack-module/model/greyattack-aodv-packet.cc b/greyattack-module/model/greyattack-aodv-packet.cc new file mode 100644 index 0000000000000000000000000000000000000000..67ae91c789d9a4002a1bdb85d3b926148babffeb --- /dev/null +++ b/greyattack-module/model/greyattack-aodv-packet.cc @@ -0,0 +1,693 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based on + * NS-3 greyattack model developed by + * + * + * Authors: Charles Hutchins + */ +#include "greyattack-aodv-packet.h" +#include "ns3/address-utils.h" +#include "ns3/packet.h" + +namespace ns3 { +namespace greyattackAodv { + +NS_OBJECT_ENSURE_REGISTERED (TypeHeader); + +TypeHeader::TypeHeader (MessageType t) + : m_type (t), + m_valid (true) +{ +} + +TypeId +TypeHeader::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::greyattack-aodv::TypeHeader") + .SetParent<Header> () + .SetGroupName ("greyattack-aodv") + .AddConstructor<TypeHeader> () + ; + return tid; +} + +TypeId +TypeHeader::GetInstanceTypeId () const +{ + return GetTypeId (); +} + +uint32_t +TypeHeader::GetSerializedSize () const +{ + return 1; +} + +void +TypeHeader::Serialize (Buffer::Iterator i) const +{ + i.WriteU8 ((uint8_t) m_type); +} + +uint32_t +TypeHeader::Deserialize (Buffer::Iterator start) +{ + Buffer::Iterator i = start; + uint8_t type = i.ReadU8 (); + m_valid = true; + switch (type) + { + case greyattackTYPE_RREQ: + case greyattackTYPE_RREP: + case greyattackTYPE_RERR: + case greyattackTYPE_RREP_ACK: + { + m_type = (MessageType) type; + break; + } + default: + m_valid = false; + } + uint32_t dist = i.GetDistanceFrom (start); + NS_ASSERT (dist == GetSerializedSize ()); + return dist; +} + +void +TypeHeader::Print (std::ostream &os) const +{ + switch (m_type) + { + case greyattackTYPE_RREQ: + { + os << "RREQ"; + break; + } + case greyattackTYPE_RREP: + { + os << "RREP"; + break; + } + case greyattackTYPE_RERR: + { + os << "RERR"; + break; + } + case greyattackTYPE_RREP_ACK: + { + os << "RREP_ACK"; + break; + } + default: + os << "UNKNOWN_TYPE"; + } +} + +bool +TypeHeader::operator== (TypeHeader const & o) const +{ + return (m_type == o.m_type && m_valid == o.m_valid); +} + +std::ostream & +operator<< (std::ostream & os, TypeHeader const & h) +{ + h.Print (os); + return os; +} + +//----------------------------------------------------------------------------- +// RREQ +//----------------------------------------------------------------------------- +RreqHeader::RreqHeader (uint8_t flags, uint8_t reserved, uint8_t hopCount, uint32_t requestID, Ipv4Address dst, + uint32_t dstSeqNo, Ipv4Address origin, uint32_t originSeqNo) + : m_AER(0.0), + m_flags (flags), + m_reserved (reserved), + m_hopCount (hopCount), + m_requestID (requestID), + m_dst (dst), + m_dstSeqNo (dstSeqNo), + m_origin (origin), + m_originSeqNo (originSeqNo) +{ +} + +NS_OBJECT_ENSURE_REGISTERED (RreqHeader); + +TypeId +RreqHeader::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::greyattack-aodv::RreqHeader") + .SetParent<Header> () + .SetGroupName ("greyattack-aodv") + .AddConstructor<RreqHeader> () + ; + return tid; +} + +TypeId +RreqHeader::GetInstanceTypeId () const +{ + return GetTypeId (); +} + +uint32_t +RreqHeader::GetSerializedSize () const +{ + return 23+4; +} + +void +RreqHeader::Serialize (Buffer::Iterator i) const +{ + i.WriteU8 (m_flags); + i.WriteU8 (m_reserved); + i.WriteU8 (m_hopCount); + i.WriteHtonU32 (m_requestID); + WriteTo (i, m_dst); + i.WriteHtonU32 (m_dstSeqNo); + WriteTo (i, m_origin); + i.WriteHtonU32 (m_originSeqNo); + + uint8_t mAER_arr[sizeof(float)]; + memcpy(mAER_arr, &m_AER, sizeof(float)); + for(uint32_t float_idx=0; float_idx<sizeof(float); float_idx++) i.WriteU8(mAER_arr[float_idx]); +} + +uint32_t +RreqHeader::Deserialize (Buffer::Iterator start) +{ + Buffer::Iterator i = start; + m_flags = i.ReadU8 (); + m_reserved = i.ReadU8 (); + m_hopCount = i.ReadU8 (); + m_requestID = i.ReadNtohU32 (); + ReadFrom (i, m_dst); + m_dstSeqNo = i.ReadNtohU32 (); + ReadFrom (i, m_origin); + m_originSeqNo = i.ReadNtohU32 (); + + uint8_t mAER_arr[sizeof(float)]; + for(uint32_t float_idx=0; float_idx<sizeof(float); float_idx++) mAER_arr[float_idx] = i.ReadU8(); + memcpy(&m_AER, mAER_arr, sizeof(float)); + + uint32_t dist = i.GetDistanceFrom (start); + NS_ASSERT (dist == GetSerializedSize ()); + return dist; +} + +void +RreqHeader::Print (std::ostream &os) const +{ + os << "RREQ ID " << m_requestID << " destination: ipv4 " << m_dst + << " sequence number " << m_dstSeqNo << " source: ipv4 " + << m_origin << " sequence number " << m_originSeqNo + << " flags:" << " Gratuitous RREP " << (*this).GetGratuitousRrep () + << " Destination only " << (*this).GetDestinationOnly () + << " Unknown sequence number " << (*this).GetUnknownSeqno () + << " Hop count " << unsigned((*this).GetHopCount()) + << "\n"; +} + +std::ostream & +operator<< (std::ostream & os, RreqHeader const & h) +{ + h.Print (os); + return os; +} + +void +RreqHeader::SetGratuitousRrep (bool f) +{ + if (f) + { + m_flags |= (1 << 5); + } + else + { + m_flags &= ~(1 << 5); + } +} + +bool +RreqHeader::GetGratuitousRrep () const +{ + return (m_flags & (1 << 5)); +} + +void +RreqHeader::SetDestinationOnly (bool f) +{ + if (f) + { + m_flags |= (1 << 4); + } + else + { + m_flags &= ~(1 << 4); + } +} + +bool +RreqHeader::GetDestinationOnly () const +{ + return (m_flags & (1 << 4)); +} + +void +RreqHeader::SetUnknownSeqno (bool f) +{ + if (f) + { + m_flags |= (1 << 3); + } + else + { + m_flags &= ~(1 << 3); + } +} + +bool +RreqHeader::GetUnknownSeqno () const +{ + return (m_flags & (1 << 3)); +} + +bool +RreqHeader::operator== (RreqHeader const & o) const +{ + return (m_flags == o.m_flags && m_reserved == o.m_reserved + && m_hopCount == o.m_hopCount && m_requestID == o.m_requestID + && m_dst == o.m_dst && m_dstSeqNo == o.m_dstSeqNo + && m_origin == o.m_origin && m_originSeqNo == o.m_originSeqNo); +} + +//----------------------------------------------------------------------------- +// RREP +//----------------------------------------------------------------------------- + +RrepHeader::RrepHeader (uint8_t prefixSize, uint8_t hopCount, Ipv4Address dst, + uint32_t dstSeqNo, Ipv4Address origin, Time lifeTime) + : m_flags (0), + m_prefixSize (prefixSize), + m_hopCount (hopCount), + m_dst (dst), + m_dstSeqNo (dstSeqNo), + m_origin (origin), + m_num_mass(0) +{ + m_lifeTime = uint32_t (lifeTime.GetMilliSeconds ()); +} + +NS_OBJECT_ENSURE_REGISTERED (RrepHeader); + +TypeId +RrepHeader::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::greyattack-aodv::RrepHeader") + .SetParent<Header> () + .SetGroupName ("greyattack-aodv") + .AddConstructor<RrepHeader> () + ; + return tid; +} + +TypeId +RrepHeader::GetInstanceTypeId () const +{ + return GetTypeId (); +} + +uint32_t +RrepHeader::GetSerializedSize () const +{ + return 19+1; +} + +void +RrepHeader::Serialize (Buffer::Iterator i) const +{ + i.WriteU8 (m_flags); + i.WriteU8 (m_prefixSize); + i.WriteU8 (m_hopCount); + WriteTo (i, m_dst); + i.WriteHtonU32 (m_dstSeqNo); + WriteTo (i, m_origin); + i.WriteHtonU32 (m_lifeTime); + i.WriteU8(m_num_mass); +} + +uint32_t +RrepHeader::Deserialize (Buffer::Iterator start) +{ + Buffer::Iterator i = start; + + m_flags = i.ReadU8 (); + m_prefixSize = i.ReadU8 (); + m_hopCount = i.ReadU8 (); + ReadFrom (i, m_dst); + m_dstSeqNo = i.ReadNtohU32 (); + ReadFrom (i, m_origin); + m_lifeTime = i.ReadNtohU32 (); + m_num_mass = i.ReadU8(); + m_num_mass = 0; + + uint32_t dist = i.GetDistanceFrom (start); + NS_ASSERT (dist == GetSerializedSize ()); + return dist; +} + +void +RrepHeader::Print (std::ostream &os) const +{ + os << "destination: ipv4 " << m_dst << " sequence number " << m_dstSeqNo; + if (m_prefixSize != 0) + { + os << " prefix size " << m_prefixSize; + } + os << " source ipv4 " << m_origin << " lifetime " << m_lifeTime + << " acknowledgment required flag " << (*this).GetAckRequired (); +} + +void +RrepHeader::SetLifeTime (Time t) +{ + m_lifeTime = t.GetMilliSeconds (); +} + +Time +RrepHeader::GetLifeTime () const +{ + Time t (MilliSeconds (m_lifeTime)); + return t; +} + +void +RrepHeader::SetAckRequired (bool f) +{ + if (f) + { + m_flags |= (1 << 6); + } + else + { + m_flags &= ~(1 << 6); + } +} + +bool +RrepHeader::GetAckRequired () const +{ + return (m_flags & (1 << 6)); +} + +void +RrepHeader::SetPrefixSize (uint8_t sz) +{ + m_prefixSize = sz; +} + +uint8_t +RrepHeader::GetPrefixSize () const +{ + return m_prefixSize; +} + +bool +RrepHeader::operator== (RrepHeader const & o) const +{ + return (m_flags == o.m_flags && m_prefixSize == o.m_prefixSize + && m_hopCount == o.m_hopCount && m_dst == o.m_dst && m_dstSeqNo == o.m_dstSeqNo + && m_origin == o.m_origin && m_lifeTime == o.m_lifeTime); +} + +void +RrepHeader::SetHello (Ipv4Address origin, uint32_t srcSeqNo, Time lifetime) +{ + m_flags = 0; + m_prefixSize = 0; + m_hopCount = 0; + m_dst = origin; + m_dstSeqNo = srcSeqNo; + m_origin = origin; + m_lifeTime = lifetime.GetMilliSeconds (); +} + +std::ostream & +operator<< (std::ostream & os, RrepHeader const & h) +{ + h.Print (os); + return os; +} + +//----------------------------------------------------------------------------- +// RREP-ACK +//----------------------------------------------------------------------------- + +RrepAckHeader::RrepAckHeader () + : m_reserved (0) +{ +} + +NS_OBJECT_ENSURE_REGISTERED (RrepAckHeader); + +TypeId +RrepAckHeader::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::greyattack-aodv::RrepAckHeader") + .SetParent<Header> () + .SetGroupName ("greyattack-aodv") + .AddConstructor<RrepAckHeader> () + ; + return tid; +} + +TypeId +RrepAckHeader::GetInstanceTypeId () const +{ + return GetTypeId (); +} + +uint32_t +RrepAckHeader::GetSerializedSize () const +{ + return 1; +} + +void +RrepAckHeader::Serialize (Buffer::Iterator i ) const +{ + i.WriteU8 (m_reserved); +} + +uint32_t +RrepAckHeader::Deserialize (Buffer::Iterator start ) +{ + Buffer::Iterator i = start; + m_reserved = i.ReadU8 (); + uint32_t dist = i.GetDistanceFrom (start); + NS_ASSERT (dist == GetSerializedSize ()); + return dist; +} + +void +RrepAckHeader::Print (std::ostream &os ) const +{ +} + +bool +RrepAckHeader::operator== (RrepAckHeader const & o ) const +{ + return m_reserved == o.m_reserved; +} + +std::ostream & +operator<< (std::ostream & os, RrepAckHeader const & h ) +{ + h.Print (os); + return os; +} + +//----------------------------------------------------------------------------- +// RERR +//----------------------------------------------------------------------------- +RerrHeader::RerrHeader () + : m_flag (0), + m_reserved (0) +{ +} + +NS_OBJECT_ENSURE_REGISTERED (RerrHeader); + +TypeId +RerrHeader::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::greyattack-aodv::RerrHeader") + .SetParent<Header> () + .SetGroupName ("greyattack-aodv") + .AddConstructor<RerrHeader> () + ; + return tid; +} + +TypeId +RerrHeader::GetInstanceTypeId () const +{ + return GetTypeId (); +} + +uint32_t +RerrHeader::GetSerializedSize () const +{ + return (3 + 8 * GetDestCount ()); +} + +void +RerrHeader::Serialize (Buffer::Iterator i ) const +{ + i.WriteU8 (m_flag); + i.WriteU8 (m_reserved); + i.WriteU8 (GetDestCount ()); + std::map<Ipv4Address, uint32_t>::const_iterator j; + for (j = m_unreachableDstSeqNo.begin (); j != m_unreachableDstSeqNo.end (); ++j) + { + WriteTo (i, (*j).first); + i.WriteHtonU32 ((*j).second); + } +} + +uint32_t +RerrHeader::Deserialize (Buffer::Iterator start ) +{ + Buffer::Iterator i = start; + m_flag = i.ReadU8 (); + m_reserved = i.ReadU8 (); + uint8_t dest = i.ReadU8 (); + m_unreachableDstSeqNo.clear (); + Ipv4Address address; + uint32_t seqNo; + for (uint8_t k = 0; k < dest; ++k) + { + ReadFrom (i, address); + seqNo = i.ReadNtohU32 (); + m_unreachableDstSeqNo.insert (std::make_pair (address, seqNo)); + } + + uint32_t dist = i.GetDistanceFrom (start); + NS_ASSERT (dist == GetSerializedSize ()); + return dist; +} + +void +RerrHeader::Print (std::ostream &os ) const +{ + os << "Unreachable destination (ipv4 address, seq. number):"; + std::map<Ipv4Address, uint32_t>::const_iterator j; + for (j = m_unreachableDstSeqNo.begin (); j != m_unreachableDstSeqNo.end (); ++j) + { + os << (*j).first << ", " << (*j).second; + } + os << "No delete flag " << (*this).GetNoDelete (); +} + +void +RerrHeader::SetNoDelete (bool f ) +{ + if (f) + { + m_flag |= (1 << 0); + } + else + { + m_flag &= ~(1 << 0); + } +} + +bool +RerrHeader::GetNoDelete () const +{ + return (m_flag & (1 << 0)); +} + +bool +RerrHeader::AddUnDestination (Ipv4Address dst, uint32_t seqNo ) +{ + if (m_unreachableDstSeqNo.find (dst) != m_unreachableDstSeqNo.end ()) + { + return true; + } + + NS_ASSERT (GetDestCount () < 255); // can't support more than 255 destinations in single RERR + m_unreachableDstSeqNo.insert (std::make_pair (dst, seqNo)); + return true; +} + +bool +RerrHeader::RemoveUnDestination (std::pair<Ipv4Address, uint32_t> & un ) +{ + if (m_unreachableDstSeqNo.empty ()) + { + return false; + } + std::map<Ipv4Address, uint32_t>::iterator i = m_unreachableDstSeqNo.begin (); + un = *i; + m_unreachableDstSeqNo.erase (i); + return true; +} + +void +RerrHeader::Clear () +{ + m_unreachableDstSeqNo.clear (); + m_flag = 0; + m_reserved = 0; +} + +bool +RerrHeader::operator== (RerrHeader const & o ) const +{ + if (m_flag != o.m_flag || m_reserved != o.m_reserved || GetDestCount () != o.GetDestCount ()) + { + return false; + } + + std::map<Ipv4Address, uint32_t>::const_iterator j = m_unreachableDstSeqNo.begin (); + std::map<Ipv4Address, uint32_t>::const_iterator k = o.m_unreachableDstSeqNo.begin (); + for (uint8_t i = 0; i < GetDestCount (); ++i) + { + if ((j->first != k->first) || (j->second != k->second)) + { + return false; + } + + j++; + k++; + } + return true; +} + +std::ostream & +operator<< (std::ostream & os, RerrHeader const & h ) +{ + h.Print (os); + return os; +} +} +} diff --git a/greyattack-module/model/greyattack-aodv-packet.h b/greyattack-module/model/greyattack-aodv-packet.h new file mode 100644 index 0000000000000000000000000000000000000000..037e8b30cf812aeec3001a0f0852e77cd94ac2e0 --- /dev/null +++ b/greyattack-module/model/greyattack-aodv-packet.h @@ -0,0 +1,632 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based on + * NS-3 greyattack model developed by + * + * Authors: Charles Hutchins + */ +#ifndef greyattack_aodvPACKET_H +#define greyattack_aodvPACKET_H + +#include <iostream> +#include "ns3/header.h" +#include "ns3/enum.h" +#include "ns3/ipv4-address.h" +#include <map> +#include "ns3/nstime.h" + +namespace ns3 { +namespace greyattackAodv { + +/** +* \ingroup greyattack +* \brief MessageType enumeration +*/ +enum MessageType +{ + greyattackTYPE_RREQ = 1, //!< greyattackTYPE_RREQ + greyattackTYPE_RREP = 2, //!< greyattackTYPE_RREP + greyattackTYPE_RERR = 3, //!< greyattackTYPE_RERR + greyattackTYPE_RREP_ACK = 4 //!< greyattackTYPE_RREP_ACK +}; + +/** +* \ingroup greyattack +* \brief greyattack types +*/ +class TypeHeader : public Header +{ +public: + /** + * constructor + * \param t the greyattack RREQ type + */ + TypeHeader (MessageType t = greyattackTYPE_RREQ); + + /** + * \brief Get the type ID. + * \return the object TypeId + */ + static TypeId GetTypeId (); + TypeId GetInstanceTypeId () const; + uint32_t GetSerializedSize () const; + void Serialize (Buffer::Iterator start) const; + uint32_t Deserialize (Buffer::Iterator start); + void Print (std::ostream &os) const; + + /** + * \returns the type + */ + MessageType Get () const + { + return m_type; + } + /** + * Check that type if valid + * \returns true if the type is valid + */ + bool IsValid () const + { + return m_valid; + } + /** + * \brief Comparison operator + * \param o header to compare + * \return true if the headers are equal + */ + bool operator== (TypeHeader const & o) const; +private: + MessageType m_type; ///< type of the message + bool m_valid; ///< Indicates if the message is valid +}; + +/** + * \brief Stream output operator + * \param os output stream + * \return updated stream + */ +std::ostream & operator<< (std::ostream & os, TypeHeader const & h); + +/** +* \ingroup greyattack +* \brief Route Request (RREQ) Message Format + \verbatim + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type |J|R|G|D|U| Reserved | Hop Count | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | RREQ ID | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Destination IP Address | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Destination Sequence Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Originator IP Address | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Originator Sequence Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + \endverbatim +*/ +class RreqHeader : public Header +{ +public: + /** + * constructor + * + * \param flags the message flags (0) + * \param reserved the reserved bits (0) + * \param hopCount the hop count + * \param requestID the request ID + * \param dst the destination IP address + * \param dstSeqNo the destination sequence number + * \param origin the origin IP address + * \param originSeqNo the origin sequence number + */ + RreqHeader (uint8_t flags = 0, uint8_t reserved = 0, uint8_t hopCount = 0, + uint32_t requestID = 0, Ipv4Address dst = Ipv4Address (), + uint32_t dstSeqNo = 0, Ipv4Address origin = Ipv4Address (), + uint32_t originSeqNo = 0); + + /** + * \brief Get the type ID. + * \return the object TypeId + */ + static TypeId GetTypeId (); + TypeId GetInstanceTypeId () const; + uint32_t GetSerializedSize () const; + void Serialize (Buffer::Iterator start) const; + uint32_t Deserialize (Buffer::Iterator start); + void Print (std::ostream &os) const; + + // Fields + /** + * \brief Set the hop count + * \param count the hop count + */ + void SetHopCount (uint8_t count) + { + m_hopCount = count; + } + /** + * \brief Get the hop count + * \return the hop count + */ + uint8_t GetHopCount () const + { + return m_hopCount; + } + /** + * \brief Set the request ID + * \param id the request ID + */ + void SetId (uint32_t id) + { + m_requestID = id; + } + /** + * \brief Get the request ID + * \return the request ID + */ + uint32_t GetId () const + { + return m_requestID; + } + /** + * \brief Set the destination address + * \param a the destination address + */ + void SetDst (Ipv4Address a) + { + m_dst = a; + } + /** + * \brief Get the destination address + * \return the destination address + */ + Ipv4Address GetDst () const + { + return m_dst; + } + /** + * \brief Set the destination sequence number + * \param s the destination sequence number + */ + void SetDstSeqno (uint32_t s) + { + m_dstSeqNo = s; + } + /** + * \brief Get the destination sequence number + * \return the destination sequence number + */ + uint32_t GetDstSeqno () const + { + return m_dstSeqNo; + } + /** + * \brief Set the origin address + * \param a the origin address + */ + void SetOrigin (Ipv4Address a) + { + m_origin = a; + } + /** + * \brief Get the origin address + * \return the origin address + */ + Ipv4Address GetOrigin () const + { + return m_origin; + } + /** + * \brief Set the origin sequence number + * \param s the origin sequence number + */ + void SetOriginSeqno (uint32_t s) + { + m_originSeqNo = s; + } + /** + * \brief Get the origin sequence number + * \return the origin sequence number + */ + uint32_t GetOriginSeqno () const + { + return m_originSeqNo; + } + + // Flags + /** + * \brief Set the gratuitous RREP flag + * \param f the gratuitous RREP flag + */ + void SetGratuitousRrep (bool f); + /** + * \brief Get the gratuitous RREP flag + * \return the gratuitous RREP flag + */ + bool GetGratuitousRrep () const; + /** + * \brief Set the Destination only flag + * \param f the Destination only flag + */ + void SetDestinationOnly (bool f); + /** + * \brief Get the Destination only flag + * \return the Destination only flag + */ + bool GetDestinationOnly () const; + /** + * \brief Set the unknown sequence number flag + * \param f the unknown sequence number flag + */ + void SetUnknownSeqno (bool f); + /** + * \brief Get the unknown sequence number flag + * \return the unknown sequence number flag + */ + bool GetUnknownSeqno () const; + + /** + * \brief Comparison operator + * \param o RREQ header to compare + * \return true if the RREQ headers are equal + */ + bool operator== (RreqHeader const & o) const; + + float m_AER; + +private: + uint8_t m_flags; ///< |J|R|G|D|U| bit flags, see RFC + uint8_t m_reserved; ///< Not used (must be 0) + uint8_t m_hopCount; ///< Hop Count + uint32_t m_requestID; ///< RREQ ID + Ipv4Address m_dst; ///< Destination IP Address + uint32_t m_dstSeqNo; ///< Destination Sequence Number + Ipv4Address m_origin; ///< Originator IP Address + uint32_t m_originSeqNo; ///< Source Sequence Number +}; + +/** + * \brief Stream output operator + * \param os output stream + * \return updated stream + */ +std::ostream & operator<< (std::ostream & os, RreqHeader const &); + +/** +* \ingroup greyattack +* \brief Route Reply (RREP) Message Format + \verbatim + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type |R|A| Reserved |Prefix Sz| Hop Count | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Destination IP address | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Destination Sequence Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Originator IP address | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Lifetime | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + \endverbatim +*/ +class RrepHeader : public Header +{ +public: + /** + * constructor + * + * \param prefixSize the prefix size (0) + * \param hopCount the hop count (0) + * \param dst the destination IP address + * \param dstSeqNo the destination sequence number + * \param origin the origin IP address + * \param lifetime the lifetime + */ + RrepHeader (uint8_t prefixSize = 0, uint8_t hopCount = 0, Ipv4Address dst = + Ipv4Address (), uint32_t dstSeqNo = 0, Ipv4Address origin = + Ipv4Address (), Time lifetime = MilliSeconds (0)); + /** + * \brief Get the type ID. + * \return the object TypeId + */ + static TypeId GetTypeId (); + TypeId GetInstanceTypeId () const; + uint32_t GetSerializedSize () const; + void Serialize (Buffer::Iterator start) const; + uint32_t Deserialize (Buffer::Iterator start); + void Print (std::ostream &os) const; + + // Fields + /** + * \brief Set the hop count + * \param count the hop count + */ + void SetHopCount (uint8_t count) + { + m_hopCount = count; + } + /** + * \brief Get the hop count + * \return the hop count + */ + uint8_t GetHopCount () const + { + return m_hopCount; + } + /** + * \brief Set the destination address + * \param a the destination address + */ + void SetDst (Ipv4Address a) + { + m_dst = a; + } + /** + * \brief Get the destination address + * \return the destination address + */ + Ipv4Address GetDst () const + { + return m_dst; + } + /** + * \brief Set the destination sequence number + * \param s the destination sequence number + */ + void SetDstSeqno (uint32_t s) + { + m_dstSeqNo = s; + } + /** + * \brief Get the destination sequence number + * \return the destination sequence number + */ + uint32_t GetDstSeqno () const + { + return m_dstSeqNo; + } + /** + * \brief Set the origin address + * \param a the origin address + */ + void SetOrigin (Ipv4Address a) + { + m_origin = a; + } + /** + * \brief Get the origin address + * \return the origin address + */ + Ipv4Address GetOrigin () const + { + return m_origin; + } + /** + * \brief Set the lifetime + * \param t the lifetime + */ + void SetLifeTime (Time t); + /** + * \brief Get the lifetime + * \return the lifetime + */ + Time GetLifeTime () const; + + // Flags + /** + * \brief Set the ack required flag + * \param f the ack required flag + */ + void SetAckRequired (bool f); + /** + * \brief get the ack required flag + * \return the ack required flag + */ + bool GetAckRequired () const; + /** + * \brief Set the prefix size + * \param sz the prefix size + */ + void SetPrefixSize (uint8_t sz); + /** + * \brief Set the pefix size + * \return the prefix size + */ + uint8_t GetPrefixSize () const; + + /** + * Configure RREP to be a Hello message + * + * \param src the source IP address + * \param srcSeqNo the source sequence number + * \param lifetime the lifetime of the message + */ + void SetHello (Ipv4Address src, uint32_t srcSeqNo, Time lifetime); + + /** + * \brief Comparison operator + * \param o RREP header to compare + * \return true if the RREP headers are equal + */ + bool operator== (RrepHeader const & o) const; +private: + uint8_t m_flags; ///< A - acknowledgment required flag + uint8_t m_prefixSize; ///< Prefix Size + uint8_t m_hopCount; ///< Hop Count + Ipv4Address m_dst; ///< Destination IP Address + uint32_t m_dstSeqNo; ///< Destination Sequence Number + Ipv4Address m_origin; ///< Source IP Address + uint32_t m_lifeTime; ///< Lifetime (in milliseconds) + uint8_t m_num_mass; /// to the defense protocol compatible with this one +}; + +/** + * \brief Stream output operator + * \param os output stream + * \return updated stream + */ +std::ostream & operator<< (std::ostream & os, RrepHeader const &); + +/** +* \ingroup greyattack +* \brief Route Reply Acknowledgment (RREP-ACK) Message Format + \verbatim + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + \endverbatim +*/ +class RrepAckHeader : public Header +{ +public: + /// constructor + RrepAckHeader (); + + /** + * \brief Get the type ID. + * \return the object TypeId + */ + static TypeId GetTypeId (); + TypeId GetInstanceTypeId () const; + uint32_t GetSerializedSize () const; + void Serialize (Buffer::Iterator start) const; + uint32_t Deserialize (Buffer::Iterator start); + void Print (std::ostream &os) const; + + /** + * \brief Comparison operator + * \param o RREP header to compare + * \return true if the RREQ headers are equal + */ + bool operator== (RrepAckHeader const & o) const; +private: + uint8_t m_reserved; ///< Not used (must be 0) +}; + +/** + * \brief Stream output operator + * \param os output stream + * \return updated stream + */ +std::ostream & operator<< (std::ostream & os, RrepAckHeader const &); + + +/** +* \ingroup greyattack +* \brief Route Error (RERR) Message Format + \verbatim + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type |N| Reserved | DestCount | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Unreachable Destination IP Address (1) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Unreachable Destination Sequence Number (1) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-| + | Additional Unreachable Destination IP Addresses (if needed) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |Additional Unreachable Destination Sequence Numbers (if needed)| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + \endverbatim +*/ +class RerrHeader : public Header +{ +public: + /// constructor + RerrHeader (); + + /** + * \brief Get the type ID. + * \return the object TypeId + */ + static TypeId GetTypeId (); + TypeId GetInstanceTypeId () const; + uint32_t GetSerializedSize () const; + void Serialize (Buffer::Iterator i) const; + uint32_t Deserialize (Buffer::Iterator start); + void Print (std::ostream &os) const; + + // No delete flag + /** + * \brief Set the no delete flag + * \param f the no delete flag + */ + void SetNoDelete (bool f); + /** + * \brief Get the no delete flag + * \return the no delete flag + */ + bool GetNoDelete () const; + + /** + * \brief Add unreachable node address and its sequence number in RERR header + * \param dst unreachable IPv4 address + * \param seqNo unreachable sequence number + * \return false if we already added maximum possible number of unreachable destinations + */ + bool AddUnDestination (Ipv4Address dst, uint32_t seqNo); + /** + * \brief Delete pair (address + sequence number) from REER header, if the number of unreachable destinations > 0 + * \param un unreachable pair (address + sequence number) + * \return true on success + */ + bool RemoveUnDestination (std::pair<Ipv4Address, uint32_t> & un); + /// Clear header + void Clear (); + /** + * \returns number of unreachable destinations in RERR message + */ + uint8_t GetDestCount () const + { + return (uint8_t)m_unreachableDstSeqNo.size (); + } + + /** + * \brief Comparison operator + * \param o RERR header to compare + * \return true if the RERR headers are equal + */ + bool operator== (RerrHeader const & o) const; +private: + uint8_t m_flag; ///< No delete flag + uint8_t m_reserved; ///< Not used (must be 0) + + /// List of Unreachable destination: IP addresses and sequence numbers + std::map<Ipv4Address, uint32_t> m_unreachableDstSeqNo; +}; + +/** + * \brief Stream output operator + * \param os output stream + * \return updated stream + */ +std::ostream & operator<< (std::ostream & os, RerrHeader const &); + +} // namespace greyattack-aodv +} // namespace ns3 + +#endif /* greyattack_aodvPACKET_H */ diff --git a/greyattack-module/model/greyattack-aodv-routing-protocol.cc b/greyattack-module/model/greyattack-aodv-routing-protocol.cc new file mode 100644 index 0000000000000000000000000000000000000000..d1c87bdc31d8b75c7481e308e1d8d02d0a032f38 --- /dev/null +++ b/greyattack-module/model/greyattack-aodv-routing-protocol.cc @@ -0,0 +1,2301 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based on + * NS-3 greyattack model developed by + * + * Authors: Charles Hutchins + */ +#define NS_LOG_APPEND_CONTEXT \ + if (m_ipv4) { std::clog << "[node " << m_ipv4->GetObject<Node> ()->GetId () << "] "; } + +#include "greyattack-aodv-routing-protocol.h" +#include "ns3/log.h" +#include "ns3/boolean.h" +#include "ns3/random-variable-stream.h" +#include "ns3/inet-socket-address.h" +#include "ns3/trace-source-accessor.h" +#include "ns3/udp-socket-factory.h" +#include "ns3/udp-l4-protocol.h" +#include "ns3/udp-header.h" +#include "ns3/wifi-net-device.h" +#include "ns3/adhoc-wifi-mac.h" +#include "ns3/wifi-mac-queue-item.h" +#include "ns3/string.h" +#include "ns3/pointer.h" +#include "ns3/double.h" +#include <algorithm> +#include <limits> + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("greyattack-aodvRoutingProtocol"); + +namespace greyattackAodv { +NS_OBJECT_ENSURE_REGISTERED (RoutingProtocol); + +/// UDP Port for greyattack control traffic +const uint32_t RoutingProtocol::greyattack_PORT = 654; + +/** +* \ingroup greyattack +* \brief Tag used by greyattack implementation +*/ +class DeferredRouteOutputTag : public Tag +{ + +public: + /** + * \brief Constructor + * \param o the output interface + */ + DeferredRouteOutputTag (int32_t o = -1) : Tag (), + m_oif (o) + { + } + + /** + * \brief Get the type ID. + * \return the object TypeId + */ + static TypeId GetTypeId () + { + static TypeId tid = TypeId ("ns3::greyattack-aodv::DeferredRouteOutputTag") + .SetParent<Tag> () + .SetGroupName ("greyattack-aodv") + .AddConstructor<DeferredRouteOutputTag> () + ; + return tid; + } + + TypeId GetInstanceTypeId () const + { + return GetTypeId (); + } + + /** + * \brief Get the output interface + * \return the output interface + */ + int32_t GetInterface () const + { + return m_oif; + } + + /** + * \brief Set the output interface + * \param oif the output interface + */ + void SetInterface (int32_t oif) + { + m_oif = oif; + } + + uint32_t GetSerializedSize () const + { + return sizeof(int32_t); + } + + void Serialize (TagBuffer i) const + { + i.WriteU32 (m_oif); + } + + void Deserialize (TagBuffer i) + { + m_oif = i.ReadU32 (); + } + + void Print (std::ostream &os) const + { + os << "DeferredRouteOutputTag: output interface = " << m_oif; + } + +private: + /// Positive if output device is fixed in RouteOutput + int32_t m_oif; +}; + +NS_OBJECT_ENSURE_REGISTERED (DeferredRouteOutputTag); + + +//----------------------------------------------------------------------------- +RoutingProtocol::RoutingProtocol () + : m_rreqRetries (2), + m_ttlStart (1), + m_ttlIncrement (2), + m_ttlThreshold (7), + m_timeoutBuffer (2), + m_rreqRateLimit (10), + m_rerrRateLimit (10), + m_activeRouteTimeout (Seconds (3)), + m_netDiameter (35), + m_nodeTraversalTime (MilliSeconds (40)), + m_netTraversalTime (Time ((2 * m_netDiameter) * m_nodeTraversalTime)), + m_pathDiscoveryTime ( Time (2 * m_netTraversalTime)), + m_myRouteTimeout (Time (2 * std::max (m_pathDiscoveryTime, m_activeRouteTimeout))), + m_helloInterval (Seconds (1)), + m_allowedHelloLoss (2), + m_deletePeriod (Time (5 * std::max (m_activeRouteTimeout, m_helloInterval))), + m_nextHopWait (m_nodeTraversalTime + MilliSeconds (10)), + m_blackListTimeout (Time (m_rreqRetries * m_netTraversalTime)), + m_maxQueueLen (64), + m_maxQueueTime (Seconds (30)), + m_destinationOnly (false), + m_gratuitousReply (true), + m_enableHello (false), + m_routingTable (m_deletePeriod), + m_queue (m_maxQueueLen, m_maxQueueTime), + m_requestId (0), + m_seqNo (0), + m_rreqIdCache (m_pathDiscoveryTime), + m_dpd (m_pathDiscoveryTime), + m_nb (m_helloInterval), + m_rreqCount (0), + m_rerrCount (0), + m_vPercentDrop(0.0), + m_vTConnection(0.0), + m_vTNeighbour(0), + m_htimer (Timer::CANCEL_ON_DESTROY), + m_rreqRateLimitTimer (Timer::CANCEL_ON_DESTROY), + m_rerrRateLimitTimer (Timer::CANCEL_ON_DESTROY), + m_lastBcastTime (Seconds (0)) +{ + m_nb.SetCallback (MakeCallback (&RoutingProtocol::SendRerrWhenBreaksLinkToNextHop, this)); + targetNodes = CreateObject<TargetNodes> (); +} + +TypeId +RoutingProtocol::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::greyattack-aodv::RoutingProtocol") + .SetParent<Ipv4RoutingProtocol> () + .SetGroupName ("greyattack-aodv") + .AddConstructor<RoutingProtocol> () + .AddAttribute ("HelloInterval", "HELLO messages emission interval.", + TimeValue (Seconds (1)), + MakeTimeAccessor (&RoutingProtocol::m_helloInterval), + MakeTimeChecker ()) + .AddAttribute ("targetNodes", "A List of nodes that we wish to target, and their signal strength", + PointerValue(), + MakePointerAccessor(&RoutingProtocol::targetNodes), + MakePointerChecker<TargetNodes>()) + .AddAttribute ("NeighbourThresh", "The Number of Neighbour threshold nodes.", + UintegerValue (0), + MakeUintegerAccessor (&RoutingProtocol::m_vTNeighbour), + MakeUintegerChecker<uint32_t> ()) + .AddAttribute ("mStrat", "The Malicious Node Strategy.", + UintegerValue (0), + MakeUintegerAccessor (&RoutingProtocol::m_strat), + MakeUintegerChecker<uint32_t> ()) + .AddAttribute ("ConnectionStrengthThreshold", + "If the connection strength to a node is greater than this value, then the packet will be dropped", + DoubleValue(0.0), MakeDoubleAccessor(&RoutingProtocol::m_vTConnection), + MakeDoubleChecker<double> ()) + .AddAttribute ("TtlStart", "Initial TTL value for RREQ.", + UintegerValue (1), + MakeUintegerAccessor (&RoutingProtocol::m_ttlStart), + MakeUintegerChecker<uint16_t> ()) + .AddAttribute ("TtlIncrement", "TTL increment for each attempt using the expanding ring search for RREQ dissemination.", + UintegerValue (2), + MakeUintegerAccessor (&RoutingProtocol::m_ttlIncrement), + MakeUintegerChecker<uint16_t> ()) + .AddAttribute ("TtlThreshold", "Maximum TTL value for expanding ring search, TTL = NetDiameter is used beyond this value.", + UintegerValue (7), + MakeUintegerAccessor (&RoutingProtocol::m_ttlThreshold), + MakeUintegerChecker<uint16_t> ()) + .AddAttribute ("TimeoutBuffer", "Provide a buffer for the timeout.", + UintegerValue (2), + MakeUintegerAccessor (&RoutingProtocol::m_timeoutBuffer), + MakeUintegerChecker<uint16_t> ()) + .AddAttribute ("RreqRetries", "Maximum number of retransmissions of RREQ to discover a route", + UintegerValue (2), + MakeUintegerAccessor (&RoutingProtocol::m_rreqRetries), + MakeUintegerChecker<uint32_t> ()) + .AddAttribute ("RreqRateLimit", "Maximum number of RREQ per second.", + UintegerValue (10), + MakeUintegerAccessor (&RoutingProtocol::m_rreqRateLimit), + MakeUintegerChecker<uint32_t> ()) + .AddAttribute ("RerrRateLimit", "Maximum number of RERR per second.", + UintegerValue (10), + MakeUintegerAccessor (&RoutingProtocol::m_rerrRateLimit), + MakeUintegerChecker<uint32_t> ()) + .AddAttribute ("NodeTraversalTime", "Conservative estimate of the average one hop traversal time for packets and should include " + "queuing delays, interrupt processing times and transfer times.", + TimeValue (MilliSeconds (40)), + MakeTimeAccessor (&RoutingProtocol::m_nodeTraversalTime), + MakeTimeChecker ()) + .AddAttribute ("NextHopWait", "Period of our waiting for the neighbour's RREP_ACK = 10 ms + NodeTraversalTime", + TimeValue (MilliSeconds (50)), + MakeTimeAccessor (&RoutingProtocol::m_nextHopWait), + MakeTimeChecker ()) + .AddAttribute ("ActiveRouteTimeout", "Period of time during which the route is considered to be valid", + TimeValue (Seconds (3)), + MakeTimeAccessor (&RoutingProtocol::m_activeRouteTimeout), + MakeTimeChecker ()) + .AddAttribute ("MyRouteTimeout", "Value of lifetime field in RREP generating by this node = 2 * max(ActiveRouteTimeout, PathDiscoveryTime)", + TimeValue (Seconds (11.2)), + MakeTimeAccessor (&RoutingProtocol::m_myRouteTimeout), + MakeTimeChecker ()) + .AddAttribute ("BlackListTimeout", "Time for which the node is put into the blacklist = RreqRetries * NetTraversalTime", + TimeValue (Seconds (5.6)), + MakeTimeAccessor (&RoutingProtocol::m_blackListTimeout), + MakeTimeChecker ()) + .AddAttribute ("DeletePeriod", "DeletePeriod is intended to provide an upper bound on the time for which an upstream node A " + "can have a neighbor B as an active next hop for destination D, while B has invalidated the route to D." + " = 5 * max (HelloInterval, ActiveRouteTimeout)", + TimeValue (Seconds (15)), + MakeTimeAccessor (&RoutingProtocol::m_deletePeriod), + MakeTimeChecker ()) + .AddAttribute ("NetDiameter", "Net diameter measures the maximum possible number of hops between two nodes in the network", + UintegerValue (35), + MakeUintegerAccessor (&RoutingProtocol::m_netDiameter), + MakeUintegerChecker<uint32_t> ()) + .AddAttribute ("NetTraversalTime", "Estimate of the average net traversal time = 2 * NodeTraversalTime * NetDiameter", + TimeValue (Seconds (2.8)), + MakeTimeAccessor (&RoutingProtocol::m_netTraversalTime), + MakeTimeChecker ()) + .AddAttribute ("PathDiscoveryTime", "Estimate of maximum time needed to find route in network = 2 * NetTraversalTime", + TimeValue (Seconds (5.6)), + MakeTimeAccessor (&RoutingProtocol::m_pathDiscoveryTime), + MakeTimeChecker ()) + .AddAttribute ("MaxQueueLen", "Maximum number of packets that we allow a routing protocol to buffer.", + UintegerValue (64), + MakeUintegerAccessor (&RoutingProtocol::SetMaxQueueLen, + &RoutingProtocol::GetMaxQueueLen), + MakeUintegerChecker<uint32_t> ()) + .AddAttribute ("MaxQueueTime", "Maximum time packets can be queued (in seconds)", + TimeValue (Seconds (30)), + MakeTimeAccessor (&RoutingProtocol::SetMaxQueueTime, + &RoutingProtocol::GetMaxQueueTime), + MakeTimeChecker ()) + .AddAttribute ("AllowedHelloLoss", "Number of hello messages which may be loss for valid link.", + UintegerValue (2), + MakeUintegerAccessor (&RoutingProtocol::m_allowedHelloLoss), + MakeUintegerChecker<uint16_t> ()) + .AddAttribute ("GratuitousReply", "Indicates whether a gratuitous RREP should be unicast to the node originated route discovery.", + BooleanValue (true), + MakeBooleanAccessor (&RoutingProtocol::SetGratuitousReplyFlag, + &RoutingProtocol::GetGratuitousReplyFlag), + MakeBooleanChecker ()) + .AddAttribute ("DestinationOnly", "Indicates only the destination may respond to this RREQ.", + BooleanValue (false), + MakeBooleanAccessor (&RoutingProtocol::SetDestinationOnlyFlag, + &RoutingProtocol::GetDestinationOnlyFlag), + MakeBooleanChecker ()) + .AddAttribute ("EnableHello", "Indicates whether a hello messages enable.", + BooleanValue (true), + MakeBooleanAccessor (&RoutingProtocol::SetHelloEnable, + &RoutingProtocol::GetHelloEnable), + MakeBooleanChecker ()) + .AddAttribute ("EnableBroadcast", "Indicates whether a broadcast data packets forwarding enable.", + BooleanValue (true), + MakeBooleanAccessor (&RoutingProtocol::SetBroadcastEnable, + &RoutingProtocol::GetBroadcastEnable), + MakeBooleanChecker ()) + .AddAttribute ("UniformRv", + "Access to the underlying UniformRandomVariable", + StringValue ("ns3::UniformRandomVariable"), + MakePointerAccessor (&RoutingProtocol::m_uniformRandomVariable), + MakePointerChecker<UniformRandomVariable> ()) + .AddAttribute("PercentDrop", + "The Number of Packets to drop", + DoubleValue(0.0), MakeDoubleAccessor(&RoutingProtocol::m_vPercentDrop), + MakeDoubleChecker<double> ()) + ; + return tid; +} + +void +RoutingProtocol::SetMaxQueueLen (uint32_t len) +{ + m_maxQueueLen = len; + m_queue.SetMaxQueueLen (len); +} +void +RoutingProtocol::SetMaxQueueTime (Time t) +{ + m_maxQueueTime = t; + m_queue.SetQueueTimeout (t); +} + +RoutingProtocol::~RoutingProtocol () +{ +} + +void +RoutingProtocol::DoDispose () +{ + m_ipv4 = 0; + for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::iterator iter = + m_socketAddresses.begin (); iter != m_socketAddresses.end (); iter++) + { + iter->first->Close (); + } + m_socketAddresses.clear (); + for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::iterator iter = + m_socketSubnetBroadcastAddresses.begin (); iter != m_socketSubnetBroadcastAddresses.end (); iter++) + { + iter->first->Close (); + } + m_socketSubnetBroadcastAddresses.clear (); + Ipv4RoutingProtocol::DoDispose (); +} + +void +RoutingProtocol::PrintRoutingTable (Ptr<OutputStreamWrapper> stream, Time::Unit unit) const +{ + *stream->GetStream () << "Node: " << m_ipv4->GetObject<Node> ()->GetId () + << "; Time: " << Now ().As (unit) + << ", Local time: " << m_ipv4->GetObject<Node> ()->GetLocalTime ().As (unit) + << ", greyattack-aodv Routing table" << std::endl; + + m_routingTable.Print (stream, unit); + *stream->GetStream () << std::endl; +} + +int64_t +RoutingProtocol::AssignStreams (int64_t stream) +{ + NS_LOG_FUNCTION (this << stream); + m_uniformRandomVariable->SetStream (stream); + return 1; +} + +void +RoutingProtocol::Start () +{ + NS_LOG_FUNCTION (this); + + //This seems to be a function which is called when the protocol starts operation + //by this time, we have sorted the strategies out, so lets turn it into an enum here: + strat = static_cast<AttackStratSelect>(m_strat); + + if (m_enableHello) + { + m_nb.ScheduleTimer (); + } + m_rreqRateLimitTimer.SetFunction (&RoutingProtocol::RreqRateLimitTimerExpire, + this); + m_rreqRateLimitTimer.Schedule (Seconds (1)); + + m_rerrRateLimitTimer.SetFunction (&RoutingProtocol::RerrRateLimitTimerExpire, + this); + m_rerrRateLimitTimer.Schedule (Seconds (1)); + +} + +Ptr<Ipv4Route> +RoutingProtocol::RouteOutput (Ptr<Packet> p, const Ipv4Header &header, + Ptr<NetDevice> oif, Socket::SocketErrno &sockerr) +{ + NS_LOG_FUNCTION (this << header << (oif ? oif->GetIfIndex () : 0)); + if (!p) + { + NS_LOG_DEBUG ("Packet is == 0"); + return LoopbackRoute (header, oif); // later + } + if (m_socketAddresses.empty ()) + { + sockerr = Socket::ERROR_NOROUTETOHOST; + NS_LOG_LOGIC ("No greyattack-aodv interfaces"); + Ptr<Ipv4Route> route; + return route; + } + sockerr = Socket::ERROR_NOTERROR; + Ptr<Ipv4Route> route; + Ipv4Address dst = header.GetDestination (); + RoutingTableEntry rt; + if (m_routingTable.LookupValidRoute (dst, rt)) + { + route = rt.GetRoute (); + NS_ASSERT (route != 0); + NS_LOG_DEBUG ("Exist route to " << route->GetDestination () << " from interface " << route->GetSource ()); + if (oif != 0 && route->GetOutputDevice () != oif) + { + NS_LOG_DEBUG ("Output device doesn't match. Dropped."); + sockerr = Socket::ERROR_NOROUTETOHOST; + return Ptr<Ipv4Route> (); + } + UpdateRouteLifeTime (dst, m_activeRouteTimeout); + UpdateRouteLifeTime (route->GetGateway (), m_activeRouteTimeout); + return route; + } + + // Valid route not found, in this case we return loopback. + // Actual route request will be deferred until packet will be fully formed, + // routed to loopback, received from loopback and passed to RouteInput (see below) + uint32_t iif = (oif ? m_ipv4->GetInterfaceForDevice (oif) : -1); + DeferredRouteOutputTag tag (iif); + NS_LOG_DEBUG ("Valid Route not found"); + if (!p->PeekPacketTag (tag)) + { + p->AddPacketTag (tag); + } + return LoopbackRoute (header, oif); +} + +void +RoutingProtocol::DeferredRouteOutput (Ptr<const Packet> p, const Ipv4Header & header, + UnicastForwardCallback ucb, ErrorCallback ecb) +{ + NS_LOG_FUNCTION (this << p << header); + NS_ASSERT (p != 0 && p != Ptr<Packet> ()); + + QueueEntry newEntry (p, header, ucb, ecb); + bool result = m_queue.Enqueue (newEntry); + //std::cout << "my queue size = " << m_queue.GetSize() << " after adding packet for " << header.GetDestination() << "\n"; + if (result) + { + NS_LOG_LOGIC ("Add packet " << p->GetUid () << " to queue. Protocol " << (uint16_t) header.GetProtocol ()); + RoutingTableEntry rt; + bool result = m_routingTable.LookupRoute (header.GetDestination (), rt); + if (!result || ((rt.GetFlag () != IN_SEARCH) && result)) + { + NS_LOG_LOGIC ("Send new RREQ for outbound packet to " << header.GetDestination ()); + SendRequest (header.GetDestination ()); + } + } +} + +bool +RoutingProtocol::RouteInput (Ptr<const Packet> p, const Ipv4Header &header, + Ptr<const NetDevice> idev, UnicastForwardCallback ucb, + MulticastForwardCallback mcb, LocalDeliverCallback lcb, ErrorCallback ecb) +{ + NS_LOG_FUNCTION (this << p->GetUid () << header.GetDestination () << idev->GetAddress ()); + if (m_socketAddresses.empty ()) + { + NS_LOG_LOGIC ("No greyattack-aodv interfaces"); + return false; + } + NS_ASSERT (m_ipv4 != 0); + NS_ASSERT (p != 0); + // Check if input device supports IP + NS_ASSERT (m_ipv4->GetInterfaceForDevice (idev) >= 0); + int32_t iif = m_ipv4->GetInterfaceForDevice (idev); + + Ipv4Address dst = header.GetDestination (); + Ipv4Address origin = header.GetSource (); + + // Deferred route request + if (idev == m_lo) + { + DeferredRouteOutputTag tag; + if (p->PeekPacketTag (tag)) + { + DeferredRouteOutput (p, header, ucb, ecb); + return true; + } + } + + // Duplicate of own packet + if (IsMyOwnAddress (origin)) + { + return true; + } + + // greyattack is not a multicast routing protocol + if (dst.IsMulticast ()) + { + return false; + } + + // Broadcast local delivery/forwarding + for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = + m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j) + { + Ipv4InterfaceAddress iface = j->second; + if (m_ipv4->GetInterfaceForAddress (iface.GetLocal ()) == iif) + { + if (dst == iface.GetBroadcast () || dst.IsBroadcast ()) + { + if (m_dpd.IsDuplicate (p, header)) + { + NS_LOG_DEBUG ("Duplicated packet " << p->GetUid () << " from " << origin << ". Drop."); + return true; + } + UpdateRouteLifeTime (origin, m_activeRouteTimeout); + Ptr<Packet> packet = p->Copy (); + if (lcb.IsNull () == false) + { + NS_LOG_LOGIC ("Broadcast local delivery to " << iface.GetLocal ()); + lcb (p, header, iif); + // Fall through to additional processing + } + else + { + NS_LOG_ERROR ("Unable to deliver packet locally due to null callback " << p->GetUid () << " from " << origin); + ecb (p, header, Socket::ERROR_NOROUTETOHOST); + } + if (!m_enableBroadcast) + { + return true; + } + if (header.GetProtocol () == UdpL4Protocol::PROT_NUMBER) + { + UdpHeader udpHeader; + p->PeekHeader (udpHeader); + if (udpHeader.GetDestinationPort () == greyattack_PORT) + { + // greyattack packets sent in broadcast are already managed + return true; + } + } + if (header.GetTtl () > 1) + { + NS_LOG_LOGIC ("Forward broadcast. TTL " << (uint16_t) header.GetTtl ()); + RoutingTableEntry toBroadcast; + if (m_routingTable.LookupRoute (dst, toBroadcast)) + { + Ptr<Ipv4Route> route = toBroadcast.GetRoute (); + ucb (route, packet, header); + } + else + { + NS_LOG_DEBUG ("No route to forward broadcast. Drop packet " << p->GetUid ()); + } + } + else + { + NS_LOG_DEBUG ("TTL exceeded. Drop packet " << p->GetUid ()); + } + return true; + } + } + } + + // Unicast local delivery + if (m_ipv4->IsDestinationAddress (dst, iif)) + { + UpdateRouteLifeTime (origin, m_activeRouteTimeout); + RoutingTableEntry toOrigin; + if (m_routingTable.LookupValidRoute (origin, toOrigin)) + { + UpdateRouteLifeTime (toOrigin.GetNextHop (), m_activeRouteTimeout); + m_nb.Update (toOrigin.GetNextHop (), m_activeRouteTimeout); + } + if (lcb.IsNull () == false) + { + NS_LOG_LOGIC ("Unicast local delivery to " << dst); + lcb (p, header, iif); + } + else + { + NS_LOG_ERROR ("Unable to deliver packet locally due to null callback " << p->GetUid () << " from " << origin); + ecb (p, header, Socket::ERROR_NOROUTETOHOST); + } + return true; + } + + // Check if input device supports IP forwarding + if (m_ipv4->IsForwarding (iif) == false) + { + NS_LOG_LOGIC ("Forwarding disabled for this interface"); + ecb (p, header, Socket::ERROR_NOROUTETOHOST); + return true; + } + + // Forwarding + return Forwarding (p, header, ucb, ecb); +} + +bool +RoutingProtocol::Forwarding (Ptr<const Packet> p, const Ipv4Header & header, + UnicastForwardCallback ucb, ErrorCallback ecb) +{ + NS_LOG_FUNCTION (this); + Ipv4Address dst = header.GetDestination (); + Ipv4Address origin = header.GetSource (); + uint16_t packetID = header.GetIdentification(); + m_routingTable.Purge (); + RoutingTableEntry toDst; + if (m_routingTable.LookupRoute (dst, toDst)) + { + if (toDst.GetFlag () == VALID) + { + Ptr<Ipv4Route> route = toDst.GetRoute (); + NS_LOG_LOGIC (route->GetSource () << " forwarding to " << dst << " from " << origin << " packet " << p->GetUid ()); + + /* + * Each time a route is used to forward a data packet, its Active Route + * Lifetime field of the source, destination and the next hop on the + * path to the destination is updated to be no less than the current + * time plus ActiveRouteTimeout. + */ + UpdateRouteLifeTime (origin, m_activeRouteTimeout); + UpdateRouteLifeTime (dst, m_activeRouteTimeout); + UpdateRouteLifeTime (route->GetGateway (), m_activeRouteTimeout); + /* + * Since the route between each originator and destination pair is expected to be symmetric, the + * Active Route Lifetime for the previous hop, along the reverse path back to the IP source, is also updated + * to be no less than the current time plus ActiveRouteTimeout + */ + RoutingTableEntry toOrigin; + m_routingTable.LookupRoute (origin, toOrigin); + UpdateRouteLifeTime (toOrigin.GetNextHop (), m_activeRouteTimeout); + + m_nb.Update (route->GetGateway (), m_activeRouteTimeout); + m_nb.Update (toOrigin.GetNextHop (), m_activeRouteTimeout); + + switch(strat) + { + case PACKET_DROP_PERC:{ + ////randomly drop packets a certain percent of the time - but otherwise act normally. + NS_LOG_ERROR("Strategy PACKET_DROP_SELECT selected"); + + Ptr<UniformRandomVariable> rng = CreateObject<UniformRandomVariable>(); + rng->SetAttribute ("Min", DoubleValue (0)); + rng->SetAttribute ("Max", DoubleValue (1)); + + double randomDouble = rng->GetValue(); + if (randomDouble < m_vPercentDrop && p->GetSize() > 400) { + NS_LOG_ERROR("[Attack - PACKET_DROP_PERC]: Dropped packet " << packetID << " where the next hop was " + << toDst.GetNextHop()); + return false; + } + break; + } + case PACKET_DROP_CONNECTION:{ + //// drops packets when the connection to the next hop node is at or above a pre-set threshold value + NS_LOG_ERROR("Strategy PACKET_DROP_CONNECTION selected"); + + // Get the node number from destination address and the precursor nodes + uint8_t buf[4]; + std::vector<Ipv4Address> precursors; + double precur_connection_strength = 0.0; + uint32_t precur_node = 999; + + toDst.GetNextHop().Serialize(buf); + toDst.GetPrecursors (precursors); + + // get the node number of the target node + uint32_t index = unsigned(buf[3]) - 1; + + // check if we have updated the connection_strength vector... + if (!targetNodes->connection_strength.size()) + break; + + // get the node number of the precursor. + for(auto i : precursors) + { + uint8_t precur_buf[4]; + i.Serialize(precur_buf); + precur_node = unsigned(precur_buf[3]) - 1; + + // check if the precursor node is valid + if (precur_node >= targetNodes->connection_strength.size()) + continue; + + if(targetNodes->connection_strength[precur_node]) + { + precur_connection_strength = targetNodes->connection_strength[precur_node]; + break; + } + } + + if (targetNodes->connection_strength[index] + && precur_connection_strength < m_vTConnection + && p->GetSize() > 400) { + //i.e. if we have a less than m_vTConnection connectivity to + // our precursor... drop the packet. + + + NS_LOG_ERROR("[Attack - PACKET_DROP_CONNECTION]: Dropped packet " << packetID + << " where the next hop was " + << toDst.GetNextHop() + << " and the precursor was:" + << precur_node + << " with connection strength:" + << precur_connection_strength); + return false; + } + break; + } + case PACKET_DROP_NEIGHBOURS:{ + uint32_t neighbour_bad_con_count = 0; + NS_LOG_ERROR("[Attack - PACKET_DROP_NEIGHBOUR] Selected"); + for (auto i: targetNodes->connection_strength) + { + if(i < 1.0) { + neighbour_bad_con_count++; + } + } + if (neighbour_bad_con_count >= m_vTNeighbour) + { + NS_LOG_ERROR("[Attack - PACKET_DROP_NEIGHBOUR] neighbour_bad_con_count is: " << neighbour_bad_con_count); + return false; + } + else + break; + } + case NO_A_OPERATION:{ + // Do Nothing + NS_LOG_INFO("Strategy NO-OP selected"); + break; + } + } + + if(p->GetSize() > 400) + NS_LOG_ERROR ("forwarding packet ID: " << packetID << " ttl: " << unsigned(header.GetTtl()) << " to " << dst + << " from " << origin << " via " << toDst.GetNextHop()); + ucb(route, p, header); + return true; + } + else + { + if (toDst.GetValidSeqNo ()) + { + SendRerrWhenNoRouteToForward (dst, toDst.GetSeqNo (), origin); + NS_LOG_DEBUG ("Drop packet " << p->GetUid () << " because no route to forward it."); + NS_LOG_ERROR ("TTL is: " << unsigned(header.GetTtl())); + return false; + } + } + } + NS_LOG_LOGIC ("route not found to " << dst << ". Send RERR message."); + NS_LOG_DEBUG ("Drop packet " << p->GetUid () << " because no route to forward it."); + SendRerrWhenNoRouteToForward (dst, 0, origin); + return false; +} + +void +RoutingProtocol::SetIpv4 (Ptr<Ipv4> ipv4) +{ + NS_ASSERT (ipv4 != 0); + NS_ASSERT (m_ipv4 == 0); + + m_ipv4 = ipv4; + + // Create lo route. It is asserted that the only one interface up for now is loopback + NS_ASSERT (m_ipv4->GetNInterfaces () == 1 && m_ipv4->GetAddress (0, 0).GetLocal () == Ipv4Address ("127.0.0.1")); + m_lo = m_ipv4->GetNetDevice (0); + NS_ASSERT (m_lo != 0); + // Remember lo route + RoutingTableEntry rt (/*device=*/ m_lo, /*dst=*/ Ipv4Address::GetLoopback (), /*know seqno=*/ true, /*seqno=*/ 0, + /*iface=*/ Ipv4InterfaceAddress (Ipv4Address::GetLoopback (), Ipv4Mask ("255.0.0.0")), + /*hops=*/ 1, /*next hop=*/ Ipv4Address::GetLoopback (), + /*lifetime=*/ Simulator::GetMaximumSimulationTime ()); + m_routingTable.AddRoute (rt); + + Simulator::ScheduleNow (&RoutingProtocol::Start, this); +} + +void +RoutingProtocol::NotifyInterfaceUp (uint32_t i) +{ + NS_LOG_FUNCTION (this << m_ipv4->GetAddress (i, 0).GetLocal ()); + Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> (); + if (l3->GetNAddresses (i) > 1) + { + NS_LOG_WARN ("greyattack does not work with more then one address per each interface."); + } + Ipv4InterfaceAddress iface = l3->GetAddress (i, 0); + if (iface.GetLocal () == Ipv4Address ("127.0.0.1")) + { + return; + } + + // Create a socket to listen only on this interface + Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (), + UdpSocketFactory::GetTypeId ()); + NS_ASSERT (socket != 0); + socket->SetRecvCallback (MakeCallback (&RoutingProtocol::Recvgreyattack, this)); + socket->BindToNetDevice (l3->GetNetDevice (i)); + socket->Bind (InetSocketAddress (iface.GetLocal (), greyattack_PORT)); + socket->SetAllowBroadcast (true); + socket->SetIpRecvTtl (true); + m_socketAddresses.insert (std::make_pair (socket, iface)); + + // create also a subnet broadcast socket + socket = Socket::CreateSocket (GetObject<Node> (), + UdpSocketFactory::GetTypeId ()); + NS_ASSERT (socket != 0); + socket->SetRecvCallback (MakeCallback (&RoutingProtocol::Recvgreyattack, this)); + socket->BindToNetDevice (l3->GetNetDevice (i)); + socket->Bind (InetSocketAddress (iface.GetBroadcast (), greyattack_PORT)); + socket->SetAllowBroadcast (true); + socket->SetIpRecvTtl (true); + m_socketSubnetBroadcastAddresses.insert (std::make_pair (socket, iface)); + + // Add local broadcast record to the routing table + Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (iface.GetLocal ())); + RoutingTableEntry rt (/*device=*/ dev, /*dst=*/ iface.GetBroadcast (), /*know seqno=*/ true, /*seqno=*/ 0, /*iface=*/ iface, + /*hops=*/ 1, /*next hop=*/ iface.GetBroadcast (), /*lifetime=*/ Simulator::GetMaximumSimulationTime ()); + m_routingTable.AddRoute (rt); + + if (l3->GetInterface (i)->GetArpCache ()) + { + m_nb.AddArpCache (l3->GetInterface (i)->GetArpCache ()); + } + + // Allow neighbor manager use this interface for layer 2 feedback if possible + Ptr<WifiNetDevice> wifi = dev->GetObject<WifiNetDevice> (); + if (wifi == 0) + { + return; + } + Ptr<WifiMac> mac = wifi->GetMac (); + if (mac == 0) + { + return; + } + + mac->TraceConnectWithoutContext ("DroppedMpdu", MakeCallback (&RoutingProtocol::NotifyTxError, this)); +} + +void +RoutingProtocol::NotifyTxError (WifiMacDropReason reason, Ptr<const WifiMacQueueItem> mpdu) +{ + m_nb.GetTxErrorCallback ()(mpdu->GetHeader ()); +} + +void +RoutingProtocol::NotifyInterfaceDown (uint32_t i) +{ + NS_LOG_FUNCTION (this << m_ipv4->GetAddress (i, 0).GetLocal ()); + + // Disable layer 2 link state monitoring (if possible) + Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> (); + Ptr<NetDevice> dev = l3->GetNetDevice (i); + Ptr<WifiNetDevice> wifi = dev->GetObject<WifiNetDevice> (); + if (wifi != 0) + { + Ptr<WifiMac> mac = wifi->GetMac ()->GetObject<AdhocWifiMac> (); + if (mac != 0) + { + mac->TraceDisconnectWithoutContext ("DroppedMpdu", + MakeCallback (&RoutingProtocol::NotifyTxError, this)); + m_nb.DelArpCache (l3->GetInterface (i)->GetArpCache ()); + } + } + + // Close socket + Ptr<Socket> socket = FindSocketWithInterfaceAddress (m_ipv4->GetAddress (i, 0)); + NS_ASSERT (socket); + socket->Close (); + m_socketAddresses.erase (socket); + + // Close socket + socket = FindSubnetBroadcastSocketWithInterfaceAddress (m_ipv4->GetAddress (i, 0)); + NS_ASSERT (socket); + socket->Close (); + m_socketSubnetBroadcastAddresses.erase (socket); + + if (m_socketAddresses.empty ()) + { + NS_LOG_LOGIC ("No greyattack-aodv interfaces"); + m_htimer.Cancel (); + m_nb.Clear (); + m_routingTable.Clear (); + return; + } + m_routingTable.DeleteAllRoutesFromInterface (m_ipv4->GetAddress (i, 0)); +} + +void +RoutingProtocol::NotifyAddAddress (uint32_t i, Ipv4InterfaceAddress address) +{ + NS_LOG_FUNCTION (this << " interface " << i << " address " << address); + Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> (); + if (!l3->IsUp (i)) + { + return; + } + if (l3->GetNAddresses (i) == 1) + { + Ipv4InterfaceAddress iface = l3->GetAddress (i, 0); + Ptr<Socket> socket = FindSocketWithInterfaceAddress (iface); + if (!socket) + { + if (iface.GetLocal () == Ipv4Address ("127.0.0.1")) + { + return; + } + // Create a socket to listen only on this interface + Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (), + UdpSocketFactory::GetTypeId ()); + NS_ASSERT (socket != 0); + socket->SetRecvCallback (MakeCallback (&RoutingProtocol::Recvgreyattack,this)); + socket->BindToNetDevice (l3->GetNetDevice (i)); + socket->Bind (InetSocketAddress (iface.GetLocal (), greyattack_PORT)); + socket->SetAllowBroadcast (true); + m_socketAddresses.insert (std::make_pair (socket, iface)); + + // create also a subnet directed broadcast socket + socket = Socket::CreateSocket (GetObject<Node> (), + UdpSocketFactory::GetTypeId ()); + NS_ASSERT (socket != 0); + socket->SetRecvCallback (MakeCallback (&RoutingProtocol::Recvgreyattack, this)); + socket->BindToNetDevice (l3->GetNetDevice (i)); + socket->Bind (InetSocketAddress (iface.GetBroadcast (), greyattack_PORT)); + socket->SetAllowBroadcast (true); + socket->SetIpRecvTtl (true); + m_socketSubnetBroadcastAddresses.insert (std::make_pair (socket, iface)); + + // Add local broadcast record to the routing table + Ptr<NetDevice> dev = m_ipv4->GetNetDevice ( + m_ipv4->GetInterfaceForAddress (iface.GetLocal ())); + RoutingTableEntry rt (/*device=*/ dev, /*dst=*/ iface.GetBroadcast (), /*know seqno=*/ true, + /*seqno=*/ 0, /*iface=*/ iface, /*hops=*/ 1, + /*next hop=*/ iface.GetBroadcast (), /*lifetime=*/ Simulator::GetMaximumSimulationTime ()); + m_routingTable.AddRoute (rt); + } + } + else + { + NS_LOG_LOGIC ("greyattack does not work with more then one address per each interface. Ignore added address"); + } +} + +void +RoutingProtocol::NotifyRemoveAddress (uint32_t i, Ipv4InterfaceAddress address) +{ + NS_LOG_FUNCTION (this); + Ptr<Socket> socket = FindSocketWithInterfaceAddress (address); + if (socket) + { + m_routingTable.DeleteAllRoutesFromInterface (address); + socket->Close (); + m_socketAddresses.erase (socket); + + Ptr<Socket> unicastSocket = FindSubnetBroadcastSocketWithInterfaceAddress (address); + if (unicastSocket) + { + unicastSocket->Close (); + m_socketAddresses.erase (unicastSocket); + } + + Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> (); + if (l3->GetNAddresses (i)) + { + Ipv4InterfaceAddress iface = l3->GetAddress (i, 0); + // Create a socket to listen only on this interface + Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (), + UdpSocketFactory::GetTypeId ()); + NS_ASSERT (socket != 0); + socket->SetRecvCallback (MakeCallback (&RoutingProtocol::Recvgreyattack, this)); + // Bind to any IP address so that broadcasts can be received + socket->BindToNetDevice (l3->GetNetDevice (i)); + socket->Bind (InetSocketAddress (iface.GetLocal (), greyattack_PORT)); + socket->SetAllowBroadcast (true); + socket->SetIpRecvTtl (true); + m_socketAddresses.insert (std::make_pair (socket, iface)); + + // create also a unicast socket + socket = Socket::CreateSocket (GetObject<Node> (), + UdpSocketFactory::GetTypeId ()); + NS_ASSERT (socket != 0); + socket->SetRecvCallback (MakeCallback (&RoutingProtocol::Recvgreyattack, this)); + socket->BindToNetDevice (l3->GetNetDevice (i)); + socket->Bind (InetSocketAddress (iface.GetBroadcast (), greyattack_PORT)); + socket->SetAllowBroadcast (true); + socket->SetIpRecvTtl (true); + m_socketSubnetBroadcastAddresses.insert (std::make_pair (socket, iface)); + + // Add local broadcast record to the routing table + Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (iface.GetLocal ())); + RoutingTableEntry rt (/*device=*/ dev, /*dst=*/ iface.GetBroadcast (), /*know seqno=*/ true, /*seqno=*/ 0, /*iface=*/ iface, + /*hops=*/ 1, /*next hop=*/ iface.GetBroadcast (), /*lifetime=*/ Simulator::GetMaximumSimulationTime ()); + m_routingTable.AddRoute (rt); + } + if (m_socketAddresses.empty ()) + { + NS_LOG_LOGIC ("No greyattack-aodv interfaces"); + m_htimer.Cancel (); + m_nb.Clear (); + m_routingTable.Clear (); + return; + } + } + else + { + NS_LOG_LOGIC ("Remove address not participating in greyattack operation"); + } +} + +bool +RoutingProtocol::IsMyOwnAddress (Ipv4Address src) +{ + NS_LOG_FUNCTION (this << src); + for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = + m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j) + { + Ipv4InterfaceAddress iface = j->second; + if (src == iface.GetLocal ()) + { + return true; + } + } + return false; +} + +Ptr<Ipv4Route> +RoutingProtocol::LoopbackRoute (const Ipv4Header & hdr, Ptr<NetDevice> oif) const +{ + NS_LOG_FUNCTION (this << hdr); + NS_ASSERT (m_lo != 0); + Ptr<Ipv4Route> rt = Create<Ipv4Route> (); + rt->SetDestination (hdr.GetDestination ()); + // + // Source address selection here is tricky. The loopback route is + // returned when greyattack does not have a route; this causes the packet + // to be looped back and handled (cached) in RouteInput() method + // while a route is found. However, connection-oriented protocols + // like TCP need to create an endpoint four-tuple (src, src port, + // dst, dst port) and create a pseudo-header for checksumming. So, + // greyattack needs to guess correctly what the eventual source address + // will be. + // + // For single interface, single address nodes, this is not a problem. + // When there are possibly multiple outgoing interfaces, the policy + // implemented here is to pick the first available greyattack interface. + // If RouteOutput() caller specified an outgoing interface, that + // further constrains the selection of source address + // + std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = m_socketAddresses.begin (); + if (oif) + { + // Iterate to find an address on the oif device + for (j = m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j) + { + Ipv4Address addr = j->second.GetLocal (); + int32_t interface = m_ipv4->GetInterfaceForAddress (addr); + if (oif == m_ipv4->GetNetDevice (static_cast<uint32_t> (interface))) + { + rt->SetSource (addr); + break; + } + } + } + else + { + rt->SetSource (j->second.GetLocal ()); + } + NS_ASSERT_MSG (rt->GetSource () != Ipv4Address (), "Valid greyattack-aodv source address not found"); + rt->SetGateway (Ipv4Address ("127.0.0.1")); + rt->SetOutputDevice (m_lo); + return rt; +} + +void +RoutingProtocol::SendRequest (Ipv4Address dst) +{ + NS_LOG_FUNCTION ( this << dst); + // A node SHOULD NOT originate more than RREQ_RATELIMIT RREQ messages per second. + if (m_rreqCount == m_rreqRateLimit) + { + Simulator::Schedule (m_rreqRateLimitTimer.GetDelayLeft () + MicroSeconds (100), + &RoutingProtocol::SendRequest, this, dst); + return; + } + else + { + m_rreqCount++; + } + // Create RREQ header + RreqHeader rreqHeader; + rreqHeader.SetDst (dst); + + //set the AER in the header. + float currentAER = 0.0; + m_routingTable.GetAER(currentAER); + rreqHeader.m_AER = currentAER; + NS_LOG_ERROR("Sending a RREQ with AER Value: " << rreqHeader.m_AER); + + RoutingTableEntry rt; + // Using the Hop field in Routing Table to manage the expanding ring search + uint16_t ttl = m_ttlStart; + if (m_routingTable.LookupRoute (dst, rt)) + { + if (rt.GetFlag () != IN_SEARCH) + { + ttl = std::min<uint16_t> (rt.GetHop () + m_ttlIncrement, m_netDiameter); + } + else + { + ttl = rt.GetHop () + m_ttlIncrement; + if (ttl > m_ttlThreshold) + { + ttl = m_netDiameter; + } + } + if (ttl == m_netDiameter) + { + rt.IncrementRreqCnt (); + + } + if (rt.GetValidSeqNo ()) + { + rreqHeader.SetDstSeqno (rt.GetSeqNo ()); + } + else + { + rreqHeader.SetUnknownSeqno (true); + } + rt.SetHop (ttl); + rt.SetFlag (IN_SEARCH); + rt.SetLifeTime (m_pathDiscoveryTime); + m_routingTable.Update (rt); + } + else + { + rreqHeader.SetUnknownSeqno (true); + Ptr<NetDevice> dev = 0; + RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ dst, /*validSeqNo=*/ false, /*seqno=*/ 0, + /*iface=*/ Ipv4InterfaceAddress (),/*hop=*/ ttl, + /*nextHop=*/ Ipv4Address (), /*lifeTime=*/ m_pathDiscoveryTime); + // Check if TtlStart == NetDiameter + if (ttl == m_netDiameter) + { + newEntry.IncrementRreqCnt (); + } + newEntry.SetFlag (IN_SEARCH); + m_routingTable.AddRoute (newEntry); + } + + if (m_gratuitousReply) + { + rreqHeader.SetGratuitousRrep (true); + } + if (m_destinationOnly) + { + rreqHeader.SetDestinationOnly (true); + } + + m_seqNo++; + rreqHeader.SetOriginSeqno (m_seqNo); + m_requestId++; + rreqHeader.SetId (m_requestId); + + //std::cout << "Sending...\n"; + // Send RREQ as subnet directed broadcast from each interface used by greyattack + for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = + m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j) + { + + + Ptr<Socket> socket = j->first; + Ipv4InterfaceAddress iface = j->second; + + //std::cout << iface.GetLocal() << " --> " <<dst << "\n"; + rreqHeader.SetOrigin (iface.GetLocal ()); + m_rreqIdCache.IsDuplicate (iface.GetLocal (), m_requestId); + + Ptr<Packet> packet = Create<Packet> (); + SocketIpTtlTag tag; + tag.SetTtl (ttl); + packet->AddPacketTag (tag); + packet->AddHeader (rreqHeader); + TypeHeader tHeader (greyattackTYPE_RREQ); + packet->AddHeader (tHeader); + // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise + Ipv4Address destination; + if (iface.GetMask () == Ipv4Mask::GetOnes ()) + { + destination = Ipv4Address ("255.255.255.255"); + } + else + { + destination = iface.GetBroadcast (); + } + NS_LOG_DEBUG ("Send RREQ with id " << rreqHeader.GetId () << " to socket"); + m_lastBcastTime = Simulator::Now (); + Simulator::Schedule (Time (MilliSeconds (m_uniformRandomVariable->GetInteger (0, 10))), &RoutingProtocol::SendTo, this, socket, packet, destination); + } + ScheduleRreqRetry (dst); +} + +void +RoutingProtocol::SendTo (Ptr<Socket> socket, Ptr<Packet> packet, Ipv4Address destination) +{ + socket->SendTo (packet, 0, InetSocketAddress (destination, greyattack_PORT)); + +} +void +RoutingProtocol::ScheduleRreqRetry (Ipv4Address dst) +{ + NS_LOG_FUNCTION (this << dst); + if (m_addressReqTimer.find (dst) == m_addressReqTimer.end ()) + { + Timer timer (Timer::CANCEL_ON_DESTROY); + m_addressReqTimer[dst] = timer; + } + m_addressReqTimer[dst].SetFunction (&RoutingProtocol::RouteRequestTimerExpire, this); + m_addressReqTimer[dst].Cancel (); + m_addressReqTimer[dst].SetArguments (dst); + RoutingTableEntry rt; + m_routingTable.LookupRoute (dst, rt); + Time retry; + if (rt.GetHop () < m_netDiameter) + { + retry = 2 * m_nodeTraversalTime * (rt.GetHop () + m_timeoutBuffer); + } + else + { + NS_ABORT_MSG_UNLESS (rt.GetRreqCnt () > 0, "Unexpected value for GetRreqCount ()"); + uint16_t backoffFactor = rt.GetRreqCnt () - 1; + NS_LOG_LOGIC ("Applying binary exponential backoff factor " << backoffFactor); + retry = m_netTraversalTime * (1 << backoffFactor); + } + m_addressReqTimer[dst].Schedule (retry); + NS_LOG_LOGIC ("Scheduled RREQ retry in " << retry.As (Time::S)); +} + +void +RoutingProtocol::Recvgreyattack (Ptr<Socket> socket) +{ + NS_LOG_FUNCTION (this << socket); + Address sourceAddress; + Ptr<Packet> packet = socket->RecvFrom (sourceAddress); + InetSocketAddress inetSourceAddr = InetSocketAddress::ConvertFrom (sourceAddress); + Ipv4Address sender = inetSourceAddr.GetIpv4 (); + Ipv4Address receiver; + + if (m_socketAddresses.find (socket) != m_socketAddresses.end ()) + { + receiver = m_socketAddresses[socket].GetLocal (); + } + else if (m_socketSubnetBroadcastAddresses.find (socket) != m_socketSubnetBroadcastAddresses.end ()) + { + receiver = m_socketSubnetBroadcastAddresses[socket].GetLocal (); + } + else + { + NS_ASSERT_MSG (false, "Received a packet from an unknown socket"); + } + NS_LOG_DEBUG ("greyattack node " << this << " received a greyattack packet from " << sender << " to " << receiver); + + UpdateRouteToNeighbor (sender, receiver); + TypeHeader tHeader (greyattackTYPE_RREQ); + packet->RemoveHeader (tHeader); + if (!tHeader.IsValid ()) + { + NS_LOG_DEBUG ("greyattack message " << packet->GetUid () << " with unknown type received: " << tHeader.Get () << ". Drop"); + return; // drop + } + switch (tHeader.Get ()) + { + case greyattackTYPE_RREQ: + { + RecvRequest (packet, receiver, sender); + break; + } + case greyattackTYPE_RREP: + { + RecvReply (packet, receiver, sender); + break; + } + case greyattackTYPE_RERR: + { + RecvError (packet, sender); + break; + } + case greyattackTYPE_RREP_ACK: + { + RecvReplyAck (sender); + break; + } + } +} + +bool +RoutingProtocol::UpdateRouteLifeTime (Ipv4Address addr, Time lifetime) +{ + NS_LOG_FUNCTION (this << addr << lifetime); + RoutingTableEntry rt; + if (m_routingTable.LookupRoute (addr, rt)) + { + if (rt.GetFlag () == VALID) + { + NS_LOG_DEBUG ("Updating VALID route"); + rt.SetRreqCnt (0); + rt.SetLifeTime (std::max (lifetime, rt.GetLifeTime ())); + m_routingTable.Update (rt); + return true; + } + } + return false; +} + +void +RoutingProtocol::UpdateRouteToNeighbor (Ipv4Address sender, Ipv4Address receiver) +{ + NS_LOG_FUNCTION (this << "sender " << sender << " receiver " << receiver); + RoutingTableEntry toNeighbor; + if (!m_routingTable.LookupRoute (sender, toNeighbor)) + { + Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver)); + RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ sender, /*know seqno=*/ false, /*seqno=*/ 0, + /*iface=*/ m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0), + /*hops=*/ 1, /*next hop=*/ sender, /*lifetime=*/ m_activeRouteTimeout); + m_routingTable.AddRoute (newEntry); + } + else + { + Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver)); + if (toNeighbor.GetValidSeqNo () && (toNeighbor.GetHop () == 1) && (toNeighbor.GetOutputDevice () == dev)) + { + toNeighbor.SetLifeTime (std::max (m_activeRouteTimeout, toNeighbor.GetLifeTime ())); + + } + else + { + RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ sender, /*know seqno=*/ false, /*seqno=*/ 0, + /*iface=*/ m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0), + /*hops=*/ 1, /*next hop=*/ sender, /*lifetime=*/ std::max (m_activeRouteTimeout, toNeighbor.GetLifeTime ()) + ); + m_routingTable.Update (newEntry); + + } + } + +} + +void +RoutingProtocol::RecvRequest (Ptr<Packet> p, Ipv4Address receiver, Ipv4Address src) +{ + NS_LOG_FUNCTION (this); + RreqHeader rreqHeader; + p->RemoveHeader (rreqHeader); + + // store the AER information here. + NS_LOG_ERROR("RREQ recv which has AER value: " << rreqHeader.m_AER); + + // A node ignores all RREQs received from any node in its blacklist + RoutingTableEntry toPrev; + if (m_routingTable.LookupRoute (src, toPrev)) + { + if (toPrev.IsUnidirectional ()) + { + NS_LOG_DEBUG ("Ignoring RREQ from node in blacklist"); + return; + } + } + + uint32_t id = rreqHeader.GetId (); + Ipv4Address origin = rreqHeader.GetOrigin (); + + + + /* + * Node checks to determine whether it has received a RREQ with the same Originator IP Address and RREQ ID. + * If such a RREQ has been received, the node silently discards the newly received RREQ. + */ + if (m_rreqIdCache.IsDuplicate (origin, id)) + { + NS_LOG_DEBUG ("Ignoring RREQ due to duplicate"); + return; + } + + // Increment RREQ hop count + uint8_t hop = rreqHeader.GetHopCount () + 1; + rreqHeader.SetHopCount (hop); + + + + /* + * When the reverse route is created or updated, the following actions on the route are also carried out: + * 1. the Originator Sequence Number from the RREQ is compared to the corresponding destination sequence number + * in the route table entry and copied if greater than the existing value there + * 2. the valid sequence number field is set to true; + * 3. the next hop in the routing table becomes the node from which the RREQ was received + * 4. the hop count is copied from the Hop Count in the RREQ message; + * 5. the Lifetime is set to be the maximum of (ExistingLifetime, MinimalLifetime), where + * MinimalLifetime = current time + 2*NetTraversalTime - 2*HopCount*NodeTraversalTime + */ + RoutingTableEntry toOrigin; + if (!m_routingTable.LookupRoute (origin, toOrigin)) + { + Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver)); + RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ origin, /*validSeno=*/ true, /*seqNo=*/ rreqHeader.GetOriginSeqno (), + /*iface=*/ m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0), /*hops=*/ hop, + /*nextHop*/ src, /*timeLife=*/ Time ((2 * m_netTraversalTime - 2 * hop * m_nodeTraversalTime))); + m_routingTable.AddRoute (newEntry); + } + else + { + if (toOrigin.GetValidSeqNo ()) + { + if (int32_t (rreqHeader.GetOriginSeqno ()) - int32_t (toOrigin.GetSeqNo ()) > 0) + { + toOrigin.SetSeqNo (rreqHeader.GetOriginSeqno ()); + } + } + else + { + toOrigin.SetSeqNo (rreqHeader.GetOriginSeqno ()); + } + toOrigin.SetValidSeqNo (true); + toOrigin.SetNextHop (src); + toOrigin.SetOutputDevice (m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver))); + toOrigin.SetInterface (m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0)); + toOrigin.SetHop (hop); + toOrigin.SetLifeTime (std::max (Time (2 * m_netTraversalTime - 2 * hop * m_nodeTraversalTime), + toOrigin.GetLifeTime ())); + m_routingTable.Update (toOrigin); + //m_nb.Update (src, Time (AllowedHelloLoss * HelloInterval)); + } + + + RoutingTableEntry toNeighbor; + if (!m_routingTable.LookupRoute (src, toNeighbor)) + { + NS_LOG_DEBUG ("Neighbor:" << src << " not found in routing table. Creating an entry"); + Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver)); + RoutingTableEntry newEntry (dev, src, false, rreqHeader.GetOriginSeqno (), + m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0), + 1, src, m_activeRouteTimeout); + m_routingTable.AddRoute (newEntry); + } + else + { + toNeighbor.SetLifeTime (m_activeRouteTimeout); + toNeighbor.SetValidSeqNo (false); + toNeighbor.SetSeqNo (rreqHeader.GetOriginSeqno ()); + toNeighbor.SetFlag (VALID); + toNeighbor.SetOutputDevice (m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver))); + toNeighbor.SetInterface (m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0)); + toNeighbor.SetHop (1); + toNeighbor.SetNextHop (src); + m_routingTable.Update (toNeighbor); + } + m_nb.Update (src, Time (m_allowedHelloLoss * m_helloInterval)); + + NS_LOG_LOGIC (receiver << " receive RREQ with hop count " << static_cast<uint32_t> (rreqHeader.GetHopCount ()) + << " ID " << rreqHeader.GetId () + << " to destination " << rreqHeader.GetDst ()); + + // A node generates a RREP if either: + // (i) it is itself the destination, + if (IsMyOwnAddress (rreqHeader.GetDst ())) + { + m_routingTable.LookupRoute (origin, toOrigin); + NS_LOG_DEBUG ("Send reply since I am the destination"); + SendReply (rreqHeader, toOrigin); + return; + } + /* + * (ii) or it has an active route to the destination, the destination sequence number in the node's existing route table entry for the destination + * is valid and greater than or equal to the Destination Sequence Number of the RREQ, and the "destination only" flag is NOT set. + */ + RoutingTableEntry toDst; + Ipv4Address dst = rreqHeader.GetDst (); + if (m_routingTable.LookupRoute (dst, toDst)) + { + /* + * Drop RREQ, This node RREP will make a loop. + */ + if (toDst.GetNextHop () == src) + { + NS_LOG_DEBUG ("Drop RREQ from " << src << ", dest next hop " << toDst.GetNextHop ()); + return; + } + /* + * The Destination Sequence number for the requested destination is set to the maximum of the corresponding value + * received in the RREQ message, and the destination sequence value currently maintained by the node for the requested destination. + * However, the forwarding node MUST NOT modify its maintained value for the destination sequence number, even if the value + * received in the incoming RREQ is larger than the value currently maintained by the forwarding node. + */ + if ((rreqHeader.GetUnknownSeqno () || (int32_t (toDst.GetSeqNo ()) - int32_t (rreqHeader.GetDstSeqno ()) >= 0)) + && toDst.GetValidSeqNo () ) + { + if (!rreqHeader.GetDestinationOnly () && toDst.GetFlag () == VALID) + { + m_routingTable.LookupRoute (origin, toOrigin); + SendReplyByIntermediateNode (toDst, toOrigin, rreqHeader.GetGratuitousRrep ()); + return; + } + rreqHeader.SetDstSeqno (toDst.GetSeqNo ()); + rreqHeader.SetUnknownSeqno (false); + } + } + + SocketIpTtlTag tag; + p->RemovePacketTag (tag); + if (tag.GetTtl () < 2) + { + NS_LOG_DEBUG ("TTL exceeded. Drop RREQ origin " << src << " destination " << dst ); + return; + } + + for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = + m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j) + { + Ptr<Socket> socket = j->first; + Ipv4InterfaceAddress iface = j->second; + Ptr<Packet> packet = Create<Packet> (); + SocketIpTtlTag ttl; + + // looks like this is where we forward the RREQ on to other destinations. + // lets modify the value so it represents our AER. + float currentAER = 0.0; + float oldAER = rreqHeader.m_AER; + m_routingTable.GetAER(currentAER); + rreqHeader.m_AER = currentAER; + NS_LOG_ERROR("Forwarding(?) a RREQ with AER Value: " << rreqHeader.m_AER + << " Old Value: " << oldAER); + + ttl.SetTtl (tag.GetTtl () - 1); + packet->AddPacketTag (ttl); + packet->AddHeader (rreqHeader); + TypeHeader tHeader (greyattackTYPE_RREQ); + packet->AddHeader (tHeader); + // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise + Ipv4Address destination; + if (iface.GetMask () == Ipv4Mask::GetOnes ()) + { + destination = Ipv4Address ("255.255.255.255"); + } + else + { + destination = iface.GetBroadcast (); + } + m_lastBcastTime = Simulator::Now (); + Simulator::Schedule (Time (MilliSeconds (m_uniformRandomVariable->GetInteger (0, 10))), &RoutingProtocol::SendTo, this, socket, packet, destination); + + } +} + +void +RoutingProtocol::SendReply (RreqHeader const & rreqHeader, RoutingTableEntry const & toOrigin) +{ + NS_LOG_FUNCTION (this << toOrigin.GetDestination ()); + /* + * Destination node MUST increment its own sequence number by one if the sequence number in the RREQ packet is equal to that + * incremented value. Otherwise, the destination does not change its sequence number before generating the RREP message. + */ + if (!rreqHeader.GetUnknownSeqno () && (rreqHeader.GetDstSeqno () == m_seqNo + 1)) + { + m_seqNo++; + } + RrepHeader rrepHeader ( /*prefixSize=*/ 0, /*hops=*/ 0, /*dst=*/ rreqHeader.GetDst (), + /*dstSeqNo=*/ m_seqNo, /*origin=*/ toOrigin.GetDestination (), /*lifeTime=*/ m_myRouteTimeout); + Ptr<Packet> packet = Create<Packet> (); + SocketIpTtlTag tag; + tag.SetTtl (toOrigin.GetHop ()); + packet->AddPacketTag (tag); + packet->AddHeader (rrepHeader); + TypeHeader tHeader (greyattackTYPE_RREP); + packet->AddHeader (tHeader); + Ptr<Socket> socket = FindSocketWithInterfaceAddress (toOrigin.GetInterface ()); + NS_ASSERT (socket); + socket->SendTo (packet, 0, InetSocketAddress (toOrigin.GetNextHop (), greyattack_PORT)); +} + +void +RoutingProtocol::SendReplyByIntermediateNode (RoutingTableEntry & toDst, RoutingTableEntry & toOrigin, bool gratRep) +{ + NS_LOG_FUNCTION (this); + + + + + RrepHeader rrepHeader (/*prefix size=*/ 0, /*hops=*/ toDst.GetHop (), /*dst=*/ toDst.GetDestination (), /*dst seqno=*/ toDst.GetSeqNo (), + /*origin=*/ toOrigin.GetDestination (), /*lifetime=*/ toDst.GetLifeTime ()); + /* If the node we received a RREQ for is a neighbor we are + * probably facing a unidirectional link... Better request a RREP-ack + */ + if (toDst.GetHop () == 1) + { + rrepHeader.SetAckRequired (true); + RoutingTableEntry toNextHop; + m_routingTable.LookupRoute (toOrigin.GetNextHop (), toNextHop); + toNextHop.m_ackTimer.SetFunction (&RoutingProtocol::AckTimerExpire, this); + toNextHop.m_ackTimer.SetArguments (toNextHop.GetDestination (), m_blackListTimeout); + toNextHop.m_ackTimer.SetDelay (m_nextHopWait); + } + toDst.InsertPrecursor (toOrigin.GetNextHop ()); + toOrigin.InsertPrecursor (toDst.GetNextHop ()); + m_routingTable.Update (toDst); + m_routingTable.Update (toOrigin); + + Ptr<Packet> packet = Create<Packet> (); + SocketIpTtlTag tag; + tag.SetTtl (toOrigin.GetHop ()); + packet->AddPacketTag (tag); + packet->AddHeader (rrepHeader); + TypeHeader tHeader (greyattackTYPE_RREP); + packet->AddHeader (tHeader); + Ptr<Socket> socket = FindSocketWithInterfaceAddress (toOrigin.GetInterface ()); + NS_ASSERT (socket); + socket->SendTo (packet, 0, InetSocketAddress (toOrigin.GetNextHop (), greyattack_PORT)); + + // Generating gratuitous RREPs + if (gratRep) + { + RrepHeader gratRepHeader (/*prefix size=*/ 0, /*hops=*/ toOrigin.GetHop (), /*dst=*/ toOrigin.GetDestination (), + /*dst seqno=*/ toOrigin.GetSeqNo (), /*origin=*/ toDst.GetDestination (), + /*lifetime=*/ toOrigin.GetLifeTime ()); + Ptr<Packet> packetToDst = Create<Packet> (); + SocketIpTtlTag gratTag; + gratTag.SetTtl (toDst.GetHop ()); + packetToDst->AddPacketTag (gratTag); + packetToDst->AddHeader (gratRepHeader); + TypeHeader type (greyattackTYPE_RREP); + packetToDst->AddHeader (type); + Ptr<Socket> socket = FindSocketWithInterfaceAddress (toDst.GetInterface ()); + NS_ASSERT (socket); + NS_LOG_LOGIC ("Send gratuitous RREP " << packet->GetUid ()); + socket->SendTo (packetToDst, 0, InetSocketAddress (toDst.GetNextHop (), greyattack_PORT)); + } +} + +void +RoutingProtocol::SendReplyAck (Ipv4Address neighbor) +{ + NS_LOG_FUNCTION (this << " to " << neighbor); + RrepAckHeader h; + TypeHeader typeHeader (greyattackTYPE_RREP_ACK); + Ptr<Packet> packet = Create<Packet> (); + SocketIpTtlTag tag; + tag.SetTtl (1); + packet->AddPacketTag (tag); + packet->AddHeader (h); + packet->AddHeader (typeHeader); + RoutingTableEntry toNeighbor; + m_routingTable.LookupRoute (neighbor, toNeighbor); + Ptr<Socket> socket = FindSocketWithInterfaceAddress (toNeighbor.GetInterface ()); + NS_ASSERT (socket); + socket->SendTo (packet, 0, InetSocketAddress (neighbor, greyattack_PORT)); +} + +void +RoutingProtocol::RecvReply (Ptr<Packet> p, Ipv4Address receiver, Ipv4Address sender) +{ + NS_LOG_FUNCTION (this << " src " << sender); + RrepHeader rrepHeader; + p->RemoveHeader (rrepHeader); + Ipv4Address dst = rrepHeader.GetDst (); + NS_LOG_LOGIC ("RREP destination " << dst << " RREP origin " << rrepHeader.GetOrigin ()); + + uint8_t hop = rrepHeader.GetHopCount () + 1; + rrepHeader.SetHopCount (hop); + + // If RREP is Hello message + if (dst == rrepHeader.GetOrigin ()) + { + ProcessHello (rrepHeader, receiver); + return; + } + + /* + * If the route table entry to the destination is created or updated, then the following actions occur: + * - the route is marked as active, + * - the destination sequence number is marked as valid, + * - the next hop in the route entry is assigned to be the node from which the RREP is received, + * which is indicated by the source IP address field in the IP header, + * - the hop count is set to the value of the hop count from RREP message + 1 + * - the expiry time is set to the current time plus the value of the Lifetime in the RREP message, + * - and the destination sequence number is the Destination Sequence Number in the RREP message. + */ + Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver)); + RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ dst, /*validSeqNo=*/ true, /*seqno=*/ rrepHeader.GetDstSeqno (), + /*iface=*/ m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0),/*hop=*/ hop, + /*nextHop=*/ sender, /*lifeTime=*/ rrepHeader.GetLifeTime ()); + RoutingTableEntry toDst; + if (m_routingTable.LookupRoute (dst, toDst)) + { + /* + * The existing entry is updated only in the following circumstances: + * (i) the sequence number in the routing table is marked as invalid in route table entry. + */ + if (!toDst.GetValidSeqNo ()) + { + m_routingTable.Update (newEntry); + } + // (ii)the Destination Sequence Number in the RREP is greater than the node's copy of the destination sequence number and the known value is valid, + else if ((int32_t (rrepHeader.GetDstSeqno ()) - int32_t (toDst.GetSeqNo ())) > 0) + { + m_routingTable.Update (newEntry); + } + else + { + // (iii) the sequence numbers are the same, but the route is marked as inactive. + if ((rrepHeader.GetDstSeqno () == toDst.GetSeqNo ()) && (toDst.GetFlag () != VALID)) + { + m_routingTable.Update (newEntry); + } + // (iv) the sequence numbers are the same, and the New Hop Count is smaller than the hop count in route table entry. + else if ((rrepHeader.GetDstSeqno () == toDst.GetSeqNo ()) && (hop < toDst.GetHop ())) + { + m_routingTable.Update (newEntry); + } + } + } + else + { + // The forward route for this destination is created if it does not already exist. + NS_LOG_LOGIC ("add new route"); + m_routingTable.AddRoute (newEntry); + } + // Acknowledge receipt of the RREP by sending a RREP-ACK message back + if (rrepHeader.GetAckRequired ()) + { + SendReplyAck (sender); + rrepHeader.SetAckRequired (false); + } + NS_LOG_LOGIC ("receiver " << receiver << " origin " << rrepHeader.GetOrigin ()); + if (IsMyOwnAddress (rrepHeader.GetOrigin ())) + { + if (toDst.GetFlag () == IN_SEARCH) + { + m_routingTable.Update (newEntry); + m_addressReqTimer[dst].Cancel (); + m_addressReqTimer.erase (dst); + } + m_routingTable.LookupRoute (dst, toDst); + SendPacketFromQueue (dst, toDst.GetRoute ()); + return; + } + + RoutingTableEntry toOrigin; + if (!m_routingTable.LookupRoute (rrepHeader.GetOrigin (), toOrigin) || toOrigin.GetFlag () == IN_SEARCH) + { + return; // Impossible! drop. + } + toOrigin.SetLifeTime (std::max (m_activeRouteTimeout, toOrigin.GetLifeTime ())); + m_routingTable.Update (toOrigin); + + // Update information about precursors + if (m_routingTable.LookupValidRoute (rrepHeader.GetDst (), toDst)) + { + toDst.InsertPrecursor (toOrigin.GetNextHop ()); + m_routingTable.Update (toDst); + + RoutingTableEntry toNextHopToDst; + m_routingTable.LookupRoute (toDst.GetNextHop (), toNextHopToDst); + toNextHopToDst.InsertPrecursor (toOrigin.GetNextHop ()); + m_routingTable.Update (toNextHopToDst); + + toOrigin.InsertPrecursor (toDst.GetNextHop ()); + m_routingTable.Update (toOrigin); + + RoutingTableEntry toNextHopToOrigin; + m_routingTable.LookupRoute (toOrigin.GetNextHop (), toNextHopToOrigin); + toNextHopToOrigin.InsertPrecursor (toDst.GetNextHop ()); + m_routingTable.Update (toNextHopToOrigin); + } + SocketIpTtlTag tag; + p->RemovePacketTag (tag); + if (tag.GetTtl () < 2) + { + NS_LOG_DEBUG ("TTL exceeded. Drop RREP destination " << dst << " origin " << rrepHeader.GetOrigin ()); + return; + } + + + Ptr<Packet> packet = Create<Packet> (); + SocketIpTtlTag ttl; + ttl.SetTtl (tag.GetTtl () - 1); + packet->AddPacketTag (ttl); + packet->AddHeader (rrepHeader); + TypeHeader tHeader (greyattackTYPE_RREP); + packet->AddHeader (tHeader); + Ptr<Socket> socket = FindSocketWithInterfaceAddress (toOrigin.GetInterface ()); + NS_ASSERT (socket); + socket->SendTo (packet, 0, InetSocketAddress (toOrigin.GetNextHop (), greyattack_PORT)); +} + +void +RoutingProtocol::RecvReplyAck (Ipv4Address neighbor) +{ + NS_LOG_FUNCTION (this); + RoutingTableEntry rt; + if (m_routingTable.LookupRoute (neighbor, rt)) + { + rt.m_ackTimer.Cancel (); + rt.SetFlag (VALID); + m_routingTable.Update (rt); + } +} + +void +RoutingProtocol::ProcessHello (RrepHeader const & rrepHeader, Ipv4Address receiver ) +{ + NS_LOG_FUNCTION (this << "from " << rrepHeader.GetDst ()); + /* + * Whenever a node receives a Hello message from a neighbor, the node + * SHOULD make sure that it has an active route to the neighbor, and + * create one if necessary. + */ + RoutingTableEntry toNeighbor; + if (!m_routingTable.LookupRoute (rrepHeader.GetDst (), toNeighbor)) + { + Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver)); + RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ rrepHeader.GetDst (), /*validSeqNo=*/ true, /*seqno=*/ rrepHeader.GetDstSeqno (), + /*iface=*/ m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0), + /*hop=*/ 1, /*nextHop=*/ rrepHeader.GetDst (), /*lifeTime=*/ rrepHeader.GetLifeTime ()); + m_routingTable.AddRoute (newEntry); + } + else + { + toNeighbor.SetLifeTime (std::max (Time (m_allowedHelloLoss * m_helloInterval), toNeighbor.GetLifeTime ())); + toNeighbor.SetSeqNo (rrepHeader.GetDstSeqno ()); + toNeighbor.SetValidSeqNo (true); + toNeighbor.SetFlag (VALID); + toNeighbor.SetOutputDevice (m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver))); + toNeighbor.SetInterface (m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0)); + toNeighbor.SetHop (1); + toNeighbor.SetNextHop (rrepHeader.GetDst ()); + m_routingTable.Update (toNeighbor); + } + if (m_enableHello) + { + m_nb.Update (rrepHeader.GetDst (), Time (m_allowedHelloLoss * m_helloInterval)); + } +} + +void +RoutingProtocol::RecvError (Ptr<Packet> p, Ipv4Address src ) +{ + NS_LOG_FUNCTION (this << " from " << src); + RerrHeader rerrHeader; + p->RemoveHeader (rerrHeader); + std::map<Ipv4Address, uint32_t> dstWithNextHopSrc; + std::map<Ipv4Address, uint32_t> unreachable; + m_routingTable.GetListOfDestinationWithNextHop (src, dstWithNextHopSrc); + std::pair<Ipv4Address, uint32_t> un; + while (rerrHeader.RemoveUnDestination (un)) + { + for (std::map<Ipv4Address, uint32_t>::const_iterator i = + dstWithNextHopSrc.begin (); i != dstWithNextHopSrc.end (); ++i) + { + if (i->first == un.first) + { + unreachable.insert (un); + } + } + } + + std::vector<Ipv4Address> precursors; + for (std::map<Ipv4Address, uint32_t>::const_iterator i = unreachable.begin (); + i != unreachable.end (); ) + { + if (!rerrHeader.AddUnDestination (i->first, i->second)) + { + TypeHeader typeHeader (greyattackTYPE_RERR); + Ptr<Packet> packet = Create<Packet> (); + SocketIpTtlTag tag; + tag.SetTtl (1); + packet->AddPacketTag (tag); + packet->AddHeader (rerrHeader); + packet->AddHeader (typeHeader); + SendRerrMessage (packet, precursors); + rerrHeader.Clear (); + } + else + { + RoutingTableEntry toDst; + m_routingTable.LookupRoute (i->first, toDst); + toDst.GetPrecursors (precursors); + ++i; + } + } + if (rerrHeader.GetDestCount () != 0) + { + TypeHeader typeHeader (greyattackTYPE_RERR); + Ptr<Packet> packet = Create<Packet> (); + SocketIpTtlTag tag; + tag.SetTtl (1); + packet->AddPacketTag (tag); + packet->AddHeader (rerrHeader); + packet->AddHeader (typeHeader); + SendRerrMessage (packet, precursors); + } + m_routingTable.InvalidateRoutesWithDst (unreachable); +} + +void +RoutingProtocol::RouteRequestTimerExpire (Ipv4Address dst) +{ + NS_LOG_LOGIC (this); + RoutingTableEntry toDst; + if (m_routingTable.LookupValidRoute (dst, toDst)) + { + SendPacketFromQueue (dst, toDst.GetRoute ()); + NS_LOG_LOGIC ("route to " << dst << " found"); + return; + } + /* + * If a route discovery has been attempted RreqRetries times at the maximum TTL without + * receiving any RREP, all data packets destined for the corresponding destination SHOULD be + * dropped from the buffer and a Destination Unreachable message SHOULD be delivered to the application. + */ + if (toDst.GetRreqCnt () == m_rreqRetries) + { + NS_LOG_LOGIC ("route discovery to " << dst << " has been attempted RreqRetries (" << m_rreqRetries << ") times with ttl " << m_netDiameter); + m_addressReqTimer.erase (dst); + m_routingTable.DeleteRoute (dst); + NS_LOG_DEBUG ("Route not found. Drop all packets with dst " << dst); + m_queue.DropPacketWithDst (dst); + return; + } + + if (toDst.GetFlag () == IN_SEARCH) + { + NS_LOG_LOGIC ("Resend RREQ to " << dst << " previous ttl " << toDst.GetHop ()); + SendRequest (dst); + } + else + { + NS_LOG_DEBUG ("Route down. Stop search. Drop packet with destination " << dst); + m_addressReqTimer.erase (dst); + m_routingTable.DeleteRoute (dst); + m_queue.DropPacketWithDst (dst); + } +} + +void +RoutingProtocol::HelloTimerExpire () +{ + NS_LOG_FUNCTION (this); + Time offset = Time (Seconds (0)); + if (m_lastBcastTime > Time (Seconds (0))) + { + offset = Simulator::Now () - m_lastBcastTime; + NS_LOG_DEBUG ("Hello deferred due to last bcast at:" << m_lastBcastTime); + } + else + { + SendHello (); + } + m_htimer.Cancel (); + Time diff = m_helloInterval - offset; + m_htimer.Schedule (std::max (Time (Seconds (0)), diff)); + m_lastBcastTime = Time (Seconds (0)); +} + +void +RoutingProtocol::RreqRateLimitTimerExpire () +{ + NS_LOG_FUNCTION (this); + m_rreqCount = 0; + m_rreqRateLimitTimer.Schedule (Seconds (1)); +} + +void +RoutingProtocol::RerrRateLimitTimerExpire () +{ + NS_LOG_FUNCTION (this); + m_rerrCount = 0; + m_rerrRateLimitTimer.Schedule (Seconds (1)); +} + +void +RoutingProtocol::AckTimerExpire (Ipv4Address neighbor, Time blacklistTimeout) +{ + NS_LOG_FUNCTION (this); + m_routingTable.MarkLinkAsUnidirectional (neighbor, blacklistTimeout); +} + +void +RoutingProtocol::SendHello () +{ + NS_LOG_FUNCTION (this); + /* Broadcast a RREP with TTL = 1 with the RREP message fields set as follows: + * Destination IP Address The node's IP address. + * Destination Sequence Number The node's latest sequence number. + * Hop Count 0 + * Lifetime AllowedHelloLoss * HelloInterval + */ + for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j) + { + Ptr<Socket> socket = j->first; + Ipv4InterfaceAddress iface = j->second; + RrepHeader helloHeader (/*prefix size=*/ 0, /*hops=*/ 0, /*dst=*/ iface.GetLocal (), /*dst seqno=*/ m_seqNo, + /*origin=*/ iface.GetLocal (),/*lifetime=*/ Time (m_allowedHelloLoss * m_helloInterval)); + Ptr<Packet> packet = Create<Packet> (); + SocketIpTtlTag tag; + tag.SetTtl (1); + packet->AddPacketTag (tag); + packet->AddHeader (helloHeader); + TypeHeader tHeader (greyattackTYPE_RREP); + packet->AddHeader (tHeader); + // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise + Ipv4Address destination; + if (iface.GetMask () == Ipv4Mask::GetOnes ()) + { + destination = Ipv4Address ("255.255.255.255"); + } + else + { + destination = iface.GetBroadcast (); + } + Time jitter = Time (MilliSeconds (m_uniformRandomVariable->GetInteger (0, 10))); + Simulator::Schedule (jitter, &RoutingProtocol::SendTo, this, socket, packet, destination); + } +} + +void +RoutingProtocol::SendPacketFromQueue (Ipv4Address dst, Ptr<Ipv4Route> route) +{ + NS_LOG_FUNCTION (this); + QueueEntry queueEntry; + while (m_queue.Dequeue (dst, queueEntry)) + { + DeferredRouteOutputTag tag; + Ptr<Packet> p = ConstCast<Packet> (queueEntry.GetPacket ()); + if (p->RemovePacketTag (tag) + && tag.GetInterface () != -1 + && tag.GetInterface () != m_ipv4->GetInterfaceForDevice (route->GetOutputDevice ())) + { + NS_LOG_DEBUG ("Output device doesn't match. Dropped."); + return; + } + UnicastForwardCallback ucb = queueEntry.GetUnicastForwardCallback (); + Ipv4Header header = queueEntry.GetIpv4Header (); + header.SetSource (route->GetSource ()); + header.SetTtl (header.GetTtl () + 1); // compensate extra TTL decrement by fake loopback routing + ucb (route, p, header); + } +} + +void +RoutingProtocol::SendRerrWhenBreaksLinkToNextHop (Ipv4Address nextHop) +{ + NS_LOG_FUNCTION (this << nextHop); + RerrHeader rerrHeader; + std::vector<Ipv4Address> precursors; + std::map<Ipv4Address, uint32_t> unreachable; + + RoutingTableEntry toNextHop; + if (!m_routingTable.LookupRoute (nextHop, toNextHop)) + { + return; + } + toNextHop.GetPrecursors (precursors); + rerrHeader.AddUnDestination (nextHop, toNextHop.GetSeqNo ()); + m_routingTable.GetListOfDestinationWithNextHop (nextHop, unreachable); + for (std::map<Ipv4Address, uint32_t>::const_iterator i = unreachable.begin (); i + != unreachable.end (); ) + { + if (!rerrHeader.AddUnDestination (i->first, i->second)) + { + NS_LOG_LOGIC ("Send RERR message with maximum size."); + TypeHeader typeHeader (greyattackTYPE_RERR); + Ptr<Packet> packet = Create<Packet> (); + SocketIpTtlTag tag; + tag.SetTtl (1); + packet->AddPacketTag (tag); + packet->AddHeader (rerrHeader); + packet->AddHeader (typeHeader); + SendRerrMessage (packet, precursors); + rerrHeader.Clear (); + } + else + { + RoutingTableEntry toDst; + m_routingTable.LookupRoute (i->first, toDst); + toDst.GetPrecursors (precursors); + ++i; + } + } + if (rerrHeader.GetDestCount () != 0) + { + TypeHeader typeHeader (greyattackTYPE_RERR); + Ptr<Packet> packet = Create<Packet> (); + SocketIpTtlTag tag; + tag.SetTtl (1); + packet->AddPacketTag (tag); + packet->AddHeader (rerrHeader); + packet->AddHeader (typeHeader); + SendRerrMessage (packet, precursors); + } + unreachable.insert (std::make_pair (nextHop, toNextHop.GetSeqNo ())); + m_routingTable.InvalidateRoutesWithDst (unreachable); +} + +void +RoutingProtocol::SendRerrWhenNoRouteToForward (Ipv4Address dst, + uint32_t dstSeqNo, Ipv4Address origin) +{ + NS_LOG_FUNCTION (this); + // A node SHOULD NOT originate more than RERR_RATELIMIT RERR messages per second. + if (m_rerrCount == m_rerrRateLimit) + { + // Just make sure that the RerrRateLimit timer is running and will expire + NS_ASSERT (m_rerrRateLimitTimer.IsRunning ()); + // discard the packet and return + NS_LOG_LOGIC ("RerrRateLimit reached at " << Simulator::Now ().As (Time::S) << " with timer delay left " + << m_rerrRateLimitTimer.GetDelayLeft ().As (Time::S) + << "; suppressing RERR"); + return; + } + RerrHeader rerrHeader; + rerrHeader.AddUnDestination (dst, dstSeqNo); + RoutingTableEntry toOrigin; + Ptr<Packet> packet = Create<Packet> (); + SocketIpTtlTag tag; + tag.SetTtl (1); + packet->AddPacketTag (tag); + packet->AddHeader (rerrHeader); + packet->AddHeader (TypeHeader (greyattackTYPE_RERR)); + if (m_routingTable.LookupValidRoute (origin, toOrigin)) + { + Ptr<Socket> socket = FindSocketWithInterfaceAddress ( + toOrigin.GetInterface ()); + NS_ASSERT (socket); + NS_LOG_LOGIC ("Unicast RERR to the source of the data transmission"); + socket->SendTo (packet, 0, InetSocketAddress (toOrigin.GetNextHop (), greyattack_PORT)); + } + else + { + for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator i = + m_socketAddresses.begin (); i != m_socketAddresses.end (); ++i) + { + Ptr<Socket> socket = i->first; + Ipv4InterfaceAddress iface = i->second; + NS_ASSERT (socket); + NS_LOG_LOGIC ("Broadcast RERR message from interface " << iface.GetLocal ()); + // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise + Ipv4Address destination; + if (iface.GetMask () == Ipv4Mask::GetOnes ()) + { + destination = Ipv4Address ("255.255.255.255"); + } + else + { + destination = iface.GetBroadcast (); + } + socket->SendTo (packet->Copy (), 0, InetSocketAddress (destination, greyattack_PORT)); + } + } +} + +void +RoutingProtocol::SendRerrMessage (Ptr<Packet> packet, std::vector<Ipv4Address> precursors) +{ + NS_LOG_FUNCTION (this); + + if (precursors.empty ()) + { + NS_LOG_LOGIC ("No precursors"); + return; + } + // A node SHOULD NOT originate more than RERR_RATELIMIT RERR messages per second. + if (m_rerrCount == m_rerrRateLimit) + { + // Just make sure that the RerrRateLimit timer is running and will expire + NS_ASSERT (m_rerrRateLimitTimer.IsRunning ()); + // discard the packet and return + NS_LOG_LOGIC ("RerrRateLimit reached at " << Simulator::Now ().As (Time::S) << " with timer delay left " + << m_rerrRateLimitTimer.GetDelayLeft ().As (Time::S) + << "; suppressing RERR"); + return; + } + // If there is only one precursor, RERR SHOULD be unicast toward that precursor + if (precursors.size () == 1) + { + RoutingTableEntry toPrecursor; + if (m_routingTable.LookupValidRoute (precursors.front (), toPrecursor)) + { + Ptr<Socket> socket = FindSocketWithInterfaceAddress (toPrecursor.GetInterface ()); + NS_ASSERT (socket); + NS_LOG_LOGIC ("one precursor => unicast RERR to " << toPrecursor.GetDestination () << " from " << toPrecursor.GetInterface ().GetLocal ()); + Simulator::Schedule (Time (MilliSeconds (m_uniformRandomVariable->GetInteger (0, 10))), &RoutingProtocol::SendTo, this, socket, packet, precursors.front ()); + m_rerrCount++; + } + return; + } + + // Should only transmit RERR on those interfaces which have precursor nodes for the broken route + std::vector<Ipv4InterfaceAddress> ifaces; + RoutingTableEntry toPrecursor; + for (std::vector<Ipv4Address>::const_iterator i = precursors.begin (); i != precursors.end (); ++i) + { + if (m_routingTable.LookupValidRoute (*i, toPrecursor) + && std::find (ifaces.begin (), ifaces.end (), toPrecursor.GetInterface ()) == ifaces.end ()) + { + ifaces.push_back (toPrecursor.GetInterface ()); + } + } + + for (std::vector<Ipv4InterfaceAddress>::const_iterator i = ifaces.begin (); i != ifaces.end (); ++i) + { + Ptr<Socket> socket = FindSocketWithInterfaceAddress (*i); + NS_ASSERT (socket); + NS_LOG_LOGIC ("Broadcast RERR message from interface " << i->GetLocal ()); + // std::cout << "Broadcast RERR message from interface " << i->GetLocal () << std::endl; + // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise + Ptr<Packet> p = packet->Copy (); + Ipv4Address destination; + if (i->GetMask () == Ipv4Mask::GetOnes ()) + { + destination = Ipv4Address ("255.255.255.255"); + } + else + { + destination = i->GetBroadcast (); + } + Simulator::Schedule (Time (MilliSeconds (m_uniformRandomVariable->GetInteger (0, 10))), &RoutingProtocol::SendTo, this, socket, p, destination); + } +} + +Ptr<Socket> +RoutingProtocol::FindSocketWithInterfaceAddress (Ipv4InterfaceAddress addr ) const +{ + NS_LOG_FUNCTION (this << addr); + for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = + m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j) + { + Ptr<Socket> socket = j->first; + Ipv4InterfaceAddress iface = j->second; + if (iface == addr) + { + return socket; + } + } + Ptr<Socket> socket; + return socket; +} + +Ptr<Socket> +RoutingProtocol::FindSubnetBroadcastSocketWithInterfaceAddress (Ipv4InterfaceAddress addr ) const +{ + NS_LOG_FUNCTION (this << addr); + for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = + m_socketSubnetBroadcastAddresses.begin (); j != m_socketSubnetBroadcastAddresses.end (); ++j) + { + Ptr<Socket> socket = j->first; + Ipv4InterfaceAddress iface = j->second; + if (iface == addr) + { + return socket; + } + } + Ptr<Socket> socket; + return socket; +} + +void +RoutingProtocol::DoInitialize (void) +{ + NS_LOG_FUNCTION (this); + uint32_t startTime; + if (m_enableHello) + { + m_htimer.SetFunction (&RoutingProtocol::HelloTimerExpire, this); + startTime = m_uniformRandomVariable->GetInteger (0, 100); + NS_LOG_DEBUG ("Starting at time " << startTime << "ms"); + m_htimer.Schedule (MilliSeconds (startTime)); + } + Ipv4RoutingProtocol::DoInitialize (); +} + +} //namespace greyattack +} //namespace ns3 diff --git a/greyattack-module/model/greyattack-aodv-routing-protocol.h b/greyattack-module/model/greyattack-aodv-routing-protocol.h new file mode 100644 index 0000000000000000000000000000000000000000..0cf94db0eee693d963301eacc3541b4162da7e43 --- /dev/null +++ b/greyattack-module/model/greyattack-aodv-routing-protocol.h @@ -0,0 +1,489 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based on + * NS-3 greyattack + * + * Authors: Charles Hutchins + */ +#ifndef greyattack_aodvROUTINGPROTOCOL_H +#define greyattack_aodvROUTINGPROTOCOL_H + +#include "greyattack-aodv-rtable.h" +#include "greyattack-aodv-rqueue.h" +#include "greyattack-aodv-packet.h" +#include "greyattack-aodv-neighbor.h" +#include "greyattack-aodv-dpd.h" +#include "ns3/node.h" +#include "ns3/random-variable-stream.h" +#include "ns3/output-stream-wrapper.h" +#include "ns3/ipv4-routing-protocol.h" +#include "ns3/ipv4-interface.h" +#include "ns3/ipv4-l3-protocol.h" +#include "ns3/mobility-module.h" +#include <map> + +namespace ns3 { + +class WifiMacQueueItem; +enum WifiMacDropReason : uint8_t; // opaque enum declaration + +// Define a new class here: +class TargetNodes : public Object +{ +public: + std::vector<uint32_t> node; + std::vector<double> connection_strength; +}; + +// define a strategy enum here to distinguish between strategies: +enum AttackStratSelect +{ + NO_A_OPERATION, + PACKET_DROP_PERC, + PACKET_DROP_CONNECTION, + PACKET_DROP_NEIGHBOURS +}; + +namespace greyattackAodv { +/** + * \ingroup greyattack + * + * \brief greyattack routing protocol + */ +class RoutingProtocol : public Ipv4RoutingProtocol +{ +public: + /** + * \brief Get the type ID. + * \return the object TypeId + */ + static TypeId GetTypeId (void); + static const uint32_t greyattack_PORT; + + /// constructor + RoutingProtocol (); + virtual ~RoutingProtocol (); + virtual void DoDispose (); + + // Inherited from Ipv4RoutingProtocol + Ptr<Ipv4Route> RouteOutput (Ptr<Packet> p, const Ipv4Header &header, Ptr<NetDevice> oif, Socket::SocketErrno &sockerr); + bool RouteInput (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev, + UnicastForwardCallback ucb, MulticastForwardCallback mcb, + LocalDeliverCallback lcb, ErrorCallback ecb); + virtual void NotifyInterfaceUp (uint32_t interface); + virtual void NotifyInterfaceDown (uint32_t interface); + virtual void NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address); + virtual void NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address); + virtual void SetIpv4 (Ptr<Ipv4> ipv4); + virtual void PrintRoutingTable (Ptr<OutputStreamWrapper> stream, Time::Unit unit = Time::S) const; + + // Handle protocol parameters + /** + * Get maximum queue time + * \returns the maximum queue time + */ + Time GetMaxQueueTime () const + { + return m_maxQueueTime; + } + /** + * Set the maximum queue time + * \param t the maximum queue time + */ + void SetMaxQueueTime (Time t); + /** + * Get the maximum queue length + * \returns the maximum queue length + */ + uint32_t GetMaxQueueLen () const + { + return m_maxQueueLen; + } + /** + * Set the maximum queue length + * \param len the maximum queue length + */ + void SetMaxQueueLen (uint32_t len); + /** + * Get destination only flag + * \returns the destination only flag + */ + bool GetDestinationOnlyFlag () const + { + return m_destinationOnly; + } + /** + * Set destination only flag + * \param f the destination only flag + */ + void SetDestinationOnlyFlag (bool f) + { + m_destinationOnly = f; + } + /** + * Get gratuitous reply flag + * \returns the gratuitous reply flag + */ + bool GetGratuitousReplyFlag () const + { + return m_gratuitousReply; + } + /** + * Set gratuitous reply flag + * \param f the gratuitous reply flag + */ + void SetGratuitousReplyFlag (bool f) + { + m_gratuitousReply = f; + } + /** + * Set hello enable + * \param f the hello enable flag + */ + void SetHelloEnable (bool f) + { + m_enableHello = f; + } + /** + * Get hello enable flag + * \returns the enable hello flag + */ + bool GetHelloEnable () const + { + return m_enableHello; + } + /** + * Set broadcast enable flag + * \param f enable broadcast flag + */ + void SetBroadcastEnable (bool f) + { + m_enableBroadcast = f; + } + /** + * Get broadcast enable flag + * \returns the broadcast enable flag + */ + bool GetBroadcastEnable () const + { + return m_enableBroadcast; + } + + /** + * Assign a fixed random variable stream number to the random variables + * used by this model. Return the number of streams (possibly zero) that + * have been assigned. + * + * \param stream first stream index to use + * \return the number of stream indices assigned by this model + */ + int64_t AssignStreams (int64_t stream); + +protected: + virtual void DoInitialize (void); +private: + /** + * Notify that an MPDU was dropped. + * + * \param reason the reason why the MPDU was dropped + * \param mpdu the dropped MPDU + */ + void NotifyTxError (WifiMacDropReason reason, Ptr<const WifiMacQueueItem> mpdu); + + ////my variables for monitoring nodes + Ptr<TargetNodes> targetNodes; + + //strategy + uint32_t m_strat; + AttackStratSelect strat; + + // Protocol parameters. + uint32_t m_rreqRetries; ///< Maximum number of retransmissions of RREQ with TTL = NetDiameter to discover a route + uint16_t m_ttlStart; ///< Initial TTL value for RREQ. + uint16_t m_ttlIncrement; ///< TTL increment for each attempt using the expanding ring search for RREQ dissemination. + uint16_t m_ttlThreshold; ///< Maximum TTL value for expanding ring search, TTL = NetDiameter is used beyond this value. + uint16_t m_timeoutBuffer; ///< Provide a buffer for the timeout. + uint16_t m_rreqRateLimit; ///< Maximum number of RREQ per second. + uint16_t m_rerrRateLimit; ///< Maximum number of REER per second. + Time m_activeRouteTimeout; ///< Period of time during which the route is considered to be valid. + uint32_t m_netDiameter; ///< Net diameter measures the maximum possible number of hops between two nodes in the network + /** + * NodeTraversalTime is a conservative estimate of the average one hop traversal time for packets + * and should include queuing delays, interrupt processing times and transfer times. + */ + Time m_nodeTraversalTime; + Time m_netTraversalTime; ///< Estimate of the average net traversal time. + Time m_pathDiscoveryTime; ///< Estimate of maximum time needed to find route in network. + Time m_myRouteTimeout; ///< Value of lifetime field in RREP generating by this node. + /** + * Every HelloInterval the node checks whether it has sent a broadcast within the last HelloInterval. + * If it has not, it MAY broadcast a Hello message + */ + Time m_helloInterval; + uint32_t m_allowedHelloLoss; ///< Number of hello messages which may be loss for valid link + /** + * DeletePeriod is intended to provide an upper bound on the time for which an upstream node A + * can have a neighbor B as an active next hop for destination D, while B has invalidated the route to D. + */ + Time m_deletePeriod; + Time m_nextHopWait; ///< Period of our waiting for the neighbour's RREP_ACK + Time m_blackListTimeout; ///< Time for which the node is put into the blacklist + uint32_t m_maxQueueLen; ///< The maximum number of packets that we allow a routing protocol to buffer. + Time m_maxQueueTime; ///< The maximum period of time that a routing protocol is allowed to buffer a packet for. + bool m_destinationOnly; ///< Indicates only the destination may respond to this RREQ. + bool m_gratuitousReply; ///< Indicates whether a gratuitous RREP should be unicast to the node originated route discovery. + bool m_enableHello; ///< Indicates whether a hello messages enable + bool m_enableBroadcast; ///< Indicates whether a a broadcast data packets forwarding enable + //\} + + /// IP protocol + Ptr<Ipv4> m_ipv4; + /// Raw unicast socket per each IP interface, map socket -> iface address (IP + mask) + std::map< Ptr<Socket>, Ipv4InterfaceAddress > m_socketAddresses; + /// Raw subnet directed broadcast socket per each IP interface, map socket -> iface address (IP + mask) + std::map< Ptr<Socket>, Ipv4InterfaceAddress > m_socketSubnetBroadcastAddresses; + /// Loopback device used to defer RREQ until packet will be fully formed + Ptr<NetDevice> m_lo; + + /// Routing table + RoutingTable m_routingTable; + /// A "drop-front" queue used by the routing layer to buffer packets to which it does not have a route. + RequestQueue m_queue; + /// Broadcast ID + uint32_t m_requestId; + /// Request sequence number + uint32_t m_seqNo; + /// Handle duplicated RREQ + IdCache m_rreqIdCache; + /// Handle duplicated broadcast/multicast packets + DuplicatePacketDetection m_dpd; + /// Handle neighbors + Neighbors m_nb; + /// Number of RREQs used for RREQ rate control + uint16_t m_rreqCount; + /// Number of RERRs used for RERR rate control + uint16_t m_rerrCount; + + // My variables for the EGTA + double m_vPercentDrop; + double m_vTConnection; + uint32_t m_vTNeighbour; + +private: + /// Start protocol operation + void Start (); + /** + * Queue packet and send route request + * + * \param p the packet to route + * \param header the IP header + * \param ucb the UnicastForwardCallback function + * \param ecb the ErrorCallback function + */ + void DeferredRouteOutput (Ptr<const Packet> p, const Ipv4Header & header, UnicastForwardCallback ucb, ErrorCallback ecb); + /** + * If route exists and is valid, forward packet. + * + * \param p the packet to route + * \param header the IP header + * \param ucb the UnicastForwardCallback function + * \param ecb the ErrorCallback function + * \returns true if forwarded + */ + bool Forwarding (Ptr<const Packet> p, const Ipv4Header & header, UnicastForwardCallback ucb, ErrorCallback ecb); + /** + * Repeated attempts by a source node at route discovery for a single destination + * use the expanding ring search technique. + * \param dst the destination IP address + */ + void ScheduleRreqRetry (Ipv4Address dst); + /** + * Set lifetime field in routing table entry to the maximum of existing lifetime and lt, if the entry exists + * \param addr - destination address + * \param lt - proposed time for lifetime field in routing table entry for destination with address addr. + * \return true if route to destination address addr exist + */ + bool UpdateRouteLifeTime (Ipv4Address addr, Time lt); + /** + * Update neighbor record. + * \param receiver is supposed to be my interface + * \param sender is supposed to be IP address of my neighbor. + */ + void UpdateRouteToNeighbor (Ipv4Address sender, Ipv4Address receiver); + /** + * Test whether the provided address is assigned to an interface on this node + * \param src the source IP address + * \returns true if the IP address is the node's IP address + */ + bool IsMyOwnAddress (Ipv4Address src); + /** + * Find unicast socket with local interface address iface + * + * \param iface the interface + * \returns the socket associated with the interface + */ + Ptr<Socket> FindSocketWithInterfaceAddress (Ipv4InterfaceAddress iface) const; + /** + * Find subnet directed broadcast socket with local interface address iface + * + * \param iface the interface + * \returns the socket associated with the interface + */ + Ptr<Socket> FindSubnetBroadcastSocketWithInterfaceAddress (Ipv4InterfaceAddress iface) const; + /** + * Process hello message + * + * \param rrepHeader RREP message header + * \param receiverIfaceAddr receiver interface IP address + */ + void ProcessHello (RrepHeader const & rrepHeader, Ipv4Address receiverIfaceAddr); + /** + * Create loopback route for given header + * + * \param header the IP header + * \param oif the output interface net device + * \returns the route + */ + Ptr<Ipv4Route> LoopbackRoute (const Ipv4Header & header, Ptr<NetDevice> oif) const; + + ///\name Receive control packets + //\{ + /** + * Receive and process control packet + * \param socket input socket + */ + void Recvgreyattack (Ptr<Socket> socket); + /** + * Receive RREQ + * \param p packet + * \param receiver receiver address + * \param src sender address + */ + void RecvRequest (Ptr<Packet> p, Ipv4Address receiver, Ipv4Address src); + /** + * Receive RREP + * \param p packet + * \param my destination address + * \param src sender address + */ + void RecvReply (Ptr<Packet> p, Ipv4Address my, Ipv4Address src); + /** + * Receive RREP_ACK + * \param neighbor neighbor address + */ + void RecvReplyAck (Ipv4Address neighbor); + /** + * Receive RERR + * \param p packet + * \param src sender address + */ + /// Receive from node with address src + void RecvError (Ptr<Packet> p, Ipv4Address src); + //\} + + ///\name Send + //\{ + /** Forward packet from route request queue + * \param dst destination address + * \param route route to use + */ + void SendPacketFromQueue (Ipv4Address dst, Ptr<Ipv4Route> route); + /// Send hello + void SendHello (); + /** Send RREQ + * \param dst destination address + */ + void SendRequest (Ipv4Address dst); + /** Send RREP + * \param rreqHeader route request header + * \param toOrigin routing table entry to originator + */ + void SendReply (RreqHeader const & rreqHeader, RoutingTableEntry const & toOrigin); + /** Send RREP by intermediate node + * \param toDst routing table entry to destination + * \param toOrigin routing table entry to originator + * \param gratRep indicates whether a gratuitous RREP should be unicast to destination + */ + void SendReplyByIntermediateNode (RoutingTableEntry & toDst, RoutingTableEntry & toOrigin, bool gratRep); + /** Send RREP_ACK + * \param neighbor neighbor address + */ + void SendReplyAck (Ipv4Address neighbor); + /** Initiate RERR + * \param nextHop next hop address + */ + void SendRerrWhenBreaksLinkToNextHop (Ipv4Address nextHop); + /** Forward RERR + * \param packet packet + * \param precursors list of addresses of the visited nodes + */ + void SendRerrMessage (Ptr<Packet> packet, std::vector<Ipv4Address> precursors); + /** + * Send RERR message when no route to forward input packet. Unicast if there is reverse route to originating node, broadcast otherwise. + * \param dst - destination node IP address + * \param dstSeqNo - destination node sequence number + * \param origin - originating node IP address + */ + void SendRerrWhenNoRouteToForward (Ipv4Address dst, uint32_t dstSeqNo, Ipv4Address origin); + /// @} + + /** + * Send packet to destination socket + * \param socket - destination node socket + * \param packet - packet to send + * \param destination - destination node IP address + */ + void SendTo (Ptr<Socket> socket, Ptr<Packet> packet, Ipv4Address destination); + + /// Hello timer + Timer m_htimer; + /// Schedule next send of hello message + void HelloTimerExpire (); + /// RREQ rate limit timer + Timer m_rreqRateLimitTimer; + /// Reset RREQ count and schedule RREQ rate limit timer with delay 1 sec. + void RreqRateLimitTimerExpire (); + /// RERR rate limit timer + Timer m_rerrRateLimitTimer; + /// Reset RERR count and schedule RERR rate limit timer with delay 1 sec. + void RerrRateLimitTimerExpire (); + /// Map IP address + RREQ timer. + std::map<Ipv4Address, Timer> m_addressReqTimer; + /** + * Handle route discovery process + * \param dst the destination IP address + */ + void RouteRequestTimerExpire (Ipv4Address dst); + /** + * Mark link to neighbor node as unidirectional for blacklistTimeout + * + * \param neighbor the IP address of the neightbor node + * \param blacklistTimeout the black list timeout time + */ + void AckTimerExpire (Ipv4Address neighbor, Time blacklistTimeout); + + /// Provides uniform random variables. + Ptr<UniformRandomVariable> m_uniformRandomVariable; + /// Keep track of the last bcast time + Time m_lastBcastTime; +}; + +} //namespace greyattack +} //namespace ns3 + +#endif /* greyattackROUTINGPROTOCOL_H */ diff --git a/greyattack-module/model/greyattack-aodv-rqueue.cc b/greyattack-module/model/greyattack-aodv-rqueue.cc new file mode 100644 index 0000000000000000000000000000000000000000..adf2a8c75ff8b56760f4659a09a7a86c72e1524e --- /dev/null +++ b/greyattack-module/model/greyattack-aodv-rqueue.cc @@ -0,0 +1,160 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based on + * NS-3 greyattack + * + * Authors: Charles Hutchins + */ +#include "greyattack-aodv-rqueue.h" +#include <algorithm> +#include <functional> +#include "ns3/ipv4-route.h" +#include "ns3/socket.h" +#include "ns3/log.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("greyattack-aodvRequestQueue"); + +namespace greyattackAodv { +uint32_t +RequestQueue::GetSize () +{ + Purge (); + return m_queue.size (); +} + +bool +RequestQueue::Enqueue (QueueEntry & entry) +{ + Purge (); + for (std::vector<QueueEntry>::const_iterator i = m_queue.begin (); i + != m_queue.end (); ++i) + { + if ((i->GetPacket ()->GetUid () == entry.GetPacket ()->GetUid ()) + && (i->GetIpv4Header ().GetDestination () + == entry.GetIpv4Header ().GetDestination ())) + { + return false; + } + } + entry.SetExpireTime (m_queueTimeout); + if (m_queue.size () == m_maxLen) + { + Drop (m_queue.front (), "Drop the most aged packet"); // Drop the most aged packet + m_queue.erase (m_queue.begin ()); + } + m_queue.push_back (entry); + + return true; +} + +void +RequestQueue::DropPacketWithDst (Ipv4Address dst) +{ + NS_LOG_FUNCTION (this << dst); + Purge (); + for (std::vector<QueueEntry>::iterator i = m_queue.begin (); i + != m_queue.end (); ++i) + { + if (i->GetIpv4Header ().GetDestination () == dst) + { + Drop (*i, "DropPacketWithDst "); + } + } + auto new_end = std::remove_if (m_queue.begin (), m_queue.end (), + [&](const QueueEntry& en) { return en.GetIpv4Header ().GetDestination () == dst; }); + m_queue.erase (new_end, m_queue.end ()); +} + +bool +RequestQueue::Dequeue (Ipv4Address dst, QueueEntry & entry) +{ + Purge (); + for (std::vector<QueueEntry>::iterator i = m_queue.begin (); i != m_queue.end (); ++i) + { + if (i->GetIpv4Header ().GetDestination () == dst) + { + entry = *i; + m_queue.erase (i); + return true; + } + } + return false; +} + +bool +RequestQueue::Find (Ipv4Address dst) +{ + for (std::vector<QueueEntry>::const_iterator i = m_queue.begin (); i + != m_queue.end (); ++i) + { + if (i->GetIpv4Header ().GetDestination () == dst) + { + return true; + } + } + return false; +} + +/** + * \brief IsExpired structure + */ +struct IsExpired +{ + + /** + * Check if the entry is expired + * + * \param e QueueEntry entry + * \return true if expired, false otherwise + */ + bool + operator() (QueueEntry const & e) const + { + return (e.GetExpireTime () < Seconds (0)); + } +}; + +void +RequestQueue::Purge () +{ + IsExpired pred; + for (std::vector<QueueEntry>::iterator i = m_queue.begin (); i + != m_queue.end (); ++i) + { + if (pred (*i)) + { + Drop (*i, "Drop outdated packet "); + } + } + m_queue.erase (std::remove_if (m_queue.begin (), m_queue.end (), pred), + m_queue.end ()); +} + +void +RequestQueue::Drop (QueueEntry en, std::string reason) +{ + NS_LOG_LOGIC (reason << en.GetPacket ()->GetUid () << " " << en.GetIpv4Header ().GetDestination ()); + en.GetErrorCallback () (en.GetPacket (), en.GetIpv4Header (), + Socket::ERROR_NOROUTETOHOST); + return; +} + +} // namespace greyattack +} // namespace ns3 diff --git a/greyattack-module/model/greyattack-aodv-rqueue.h b/greyattack-module/model/greyattack-aodv-rqueue.h new file mode 100644 index 0000000000000000000000000000000000000000..f63da33c3a36c66175baa6eaea012f18b2b0538c --- /dev/null +++ b/greyattack-module/model/greyattack-aodv-rqueue.h @@ -0,0 +1,275 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based on + * NS-3 greyattack + * + * Authors: Charles Hutchins + */ +#ifndef greyattack_aodv_RQUEUE_H +#define greyattack_aodv_RQUEUE_H + +#include <vector> +#include "ns3/ipv4-routing-protocol.h" +#include "ns3/simulator.h" + + +namespace ns3 { +namespace greyattackAodv { + +/** + * \ingroup greyattack + * \brief greyattack Queue Entry + */ +class QueueEntry +{ +public: + /// IPv4 routing unicast forward callback typedef + typedef Ipv4RoutingProtocol::UnicastForwardCallback UnicastForwardCallback; + /// IPv4 routing error callback typedef + typedef Ipv4RoutingProtocol::ErrorCallback ErrorCallback; + /** + * constructor + * + * \param pa the packet to add to the queue + * \param h the Ipv4Header + * \param ucb the UnicastForwardCallback function + * \param ecb the ErrorCallback function + * \param exp the expiration time + */ + QueueEntry (Ptr<const Packet> pa = 0, Ipv4Header const & h = Ipv4Header (), + UnicastForwardCallback ucb = UnicastForwardCallback (), + ErrorCallback ecb = ErrorCallback (), Time exp = Simulator::Now ()) + : m_packet (pa), + m_header (h), + m_ucb (ucb), + m_ecb (ecb), + m_expire (exp + Simulator::Now ()) + { + } + + /** + * \brief Compare queue entries + * \param o QueueEntry to compare + * \return true if equal + */ + bool operator== (QueueEntry const & o) const + { + return ((m_packet == o.m_packet) && (m_header.GetDestination () == o.m_header.GetDestination ()) && (m_expire == o.m_expire)); + } + + // Fields + /** + * Get unicast forward callback + * \returns unicast callback + */ + UnicastForwardCallback GetUnicastForwardCallback () const + { + return m_ucb; + } + /** + * Set unicast forward callback + * \param ucb The unicast callback + */ + void SetUnicastForwardCallback (UnicastForwardCallback ucb) + { + m_ucb = ucb; + } + /** + * Get error callback + * \returns the error callback + */ + ErrorCallback GetErrorCallback () const + { + return m_ecb; + } + /** + * Set error callback + * \param ecb The error callback + */ + void SetErrorCallback (ErrorCallback ecb) + { + m_ecb = ecb; + } + /** + * Get packet from entry + * \returns the packet + */ + Ptr<const Packet> GetPacket () const + { + return m_packet; + } + /** + * Set packet in entry + * \param p The packet + */ + void SetPacket (Ptr<const Packet> p) + { + m_packet = p; + } + /** + * Get IPv4 header + * \returns the IPv4 header + */ + Ipv4Header GetIpv4Header () const + { + return m_header; + } + /** + * Set IPv4 header + * \param h the IPv4 header + */ + void SetIpv4Header (Ipv4Header h) + { + m_header = h; + } + /** + * Set expire time + * \param exp The expiration time + */ + void SetExpireTime (Time exp) + { + m_expire = exp + Simulator::Now (); + } + /** + * Get expire time + * \returns the expiration time + */ + Time GetExpireTime () const + { + return m_expire - Simulator::Now (); + } + +private: + /// Data packet + Ptr<const Packet> m_packet; + /// IP header + Ipv4Header m_header; + /// Unicast forward callback + UnicastForwardCallback m_ucb; + /// Error callback + ErrorCallback m_ecb; + /// Expire time for queue entry + Time m_expire; +}; +/** + * \ingroup greyattack + * \brief greyattack route request queue + * + * Since greyattack is an on demand routing we queue requests while looking for route. + */ +class RequestQueue +{ +public: + /** + * constructor + * + * \param maxLen the maximum length + * \param routeToQueueTimeout the route to queue timeout + */ + RequestQueue (uint32_t maxLen, Time routeToQueueTimeout) + : m_maxLen (maxLen), + m_queueTimeout (routeToQueueTimeout) + { + } + /** + * Push entry in queue, if there is no entry with the same packet and destination address in queue. + * \param entry the queue entry + * \returns true if the entry is queued + */ + bool Enqueue (QueueEntry & entry); + /** + * Return first found (the earliest) entry for given destination + * + * \param dst the destination IP address + * \param entry the queue entry + * \returns true if the entry is dequeued + */ + bool Dequeue (Ipv4Address dst, QueueEntry & entry); + /** + * Remove all packets with destination IP address dst + * \param dst the destination IP address + */ + void DropPacketWithDst (Ipv4Address dst); + /** + * Finds whether a packet with destination dst exists in the queue + * + * \param dst the destination IP address + * \returns true if an entry with the IP address is found + */ + bool Find (Ipv4Address dst); + /** + * \returns the number of entries + */ + uint32_t GetSize (); + + // Fields + /** + * Get maximum queue length + * \returns the maximum queue length + */ + uint32_t GetMaxQueueLen () const + { + return m_maxLen; + } + /** + * Set maximum queue length + * \param len The maximum queue length + */ + void SetMaxQueueLen (uint32_t len) + { + m_maxLen = len; + } + /** + * Get queue timeout + * \returns the queue timeout + */ + Time GetQueueTimeout () const + { + return m_queueTimeout; + } + /** + * Set queue timeout + * \param t The queue timeout + */ + void SetQueueTimeout (Time t) + { + m_queueTimeout = t; + } + +private: + /// The queue + std::vector<QueueEntry> m_queue; + /// Remove all expired entries + void Purge (); + /** + * Notify that packet is dropped from queue by timeout + * \param en the queue entry to drop + * \param reason the reason to drop the entry + */ + void Drop (QueueEntry en, std::string reason); + /// The maximum number of packets that we allow a routing protocol to buffer. + uint32_t m_maxLen; + /// The maximum period of time that a routing protocol is allowed to buffer a packet for, seconds. + Time m_queueTimeout; +}; + + +} // namespace greyattack +} // namespace ns3 + +#endif /* greyattack_aodv_RQUEUE_H */ diff --git a/greyattack-module/model/greyattack-aodv-rtable.cc b/greyattack-module/model/greyattack-aodv-rtable.cc new file mode 100644 index 0000000000000000000000000000000000000000..a254aa37fd39e1dae9f2419bc35ce7de3fab29df --- /dev/null +++ b/greyattack-module/model/greyattack-aodv-rtable.cc @@ -0,0 +1,583 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based on + * NS-3 greyattack + * + * Authors: Charles Hutchins + */ + +#include "greyattack-aodv-rtable.h" +#include <algorithm> +#include <iomanip> +#include "ns3/simulator.h" +#include "ns3/log.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("greyattack-aodvRoutingTable"); + +namespace greyattackAodv { + +/* + The Routing Table + */ + +RoutingTableEntry::RoutingTableEntry (Ptr<NetDevice> dev, Ipv4Address dst, bool vSeqNo, uint32_t seqNo, + Ipv4InterfaceAddress iface, uint16_t hops, Ipv4Address nextHop, Time lifetime) + : m_ackTimer (Timer::CANCEL_ON_DESTROY), + m_validSeqNo (vSeqNo), + m_seqNo (seqNo), + m_hops (hops), + m_lifeTime (lifetime + Simulator::Now ()), + m_iface (iface), + m_flag (VALID), + m_reqCount (0), + m_blackListState (false), + m_blackListTimeout (Simulator::Now ()) +{ + m_ipv4Route = Create<Ipv4Route> (); + m_ipv4Route->SetDestination (dst); + m_ipv4Route->SetGateway (nextHop); + m_ipv4Route->SetSource (m_iface.GetLocal ()); + m_ipv4Route->SetOutputDevice (dev); +} + +RoutingTableEntry::~RoutingTableEntry () +{ +} + +bool +RoutingTableEntry::InsertPrecursor (Ipv4Address id) +{ + NS_LOG_FUNCTION (this << id); + if (!LookupPrecursor (id)) + { + m_precursorList.push_back (id); + return true; + } + else + { + return false; + } +} + +bool +RoutingTableEntry::LookupPrecursor (Ipv4Address id) +{ + NS_LOG_FUNCTION (this << id); + for (std::vector<Ipv4Address>::const_iterator i = m_precursorList.begin (); i + != m_precursorList.end (); ++i) + { + if (*i == id) + { + NS_LOG_LOGIC ("Precursor " << id << " found"); + return true; + } + } + NS_LOG_LOGIC ("Precursor " << id << " not found"); + return false; +} + +bool +RoutingTableEntry::DeletePrecursor (Ipv4Address id) +{ + NS_LOG_FUNCTION (this << id); + std::vector<Ipv4Address>::iterator i = std::remove (m_precursorList.begin (), + m_precursorList.end (), id); + if (i == m_precursorList.end ()) + { + NS_LOG_LOGIC ("Precursor " << id << " not found"); + return false; + } + else + { + NS_LOG_LOGIC ("Precursor " << id << " found"); + m_precursorList.erase (i, m_precursorList.end ()); + } + return true; +} + +void +RoutingTableEntry::DeleteAllPrecursors () +{ + NS_LOG_FUNCTION (this); + m_precursorList.clear (); +} + +bool +RoutingTableEntry::IsPrecursorListEmpty () const +{ + return m_precursorList.empty (); +} + +void +RoutingTableEntry::GetPrecursors (std::vector<Ipv4Address> & prec) const +{ + NS_LOG_FUNCTION (this); + if (IsPrecursorListEmpty ()) + { + return; + } + for (std::vector<Ipv4Address>::const_iterator i = m_precursorList.begin (); i + != m_precursorList.end (); ++i) + { + bool result = true; + for (std::vector<Ipv4Address>::const_iterator j = prec.begin (); j + != prec.end (); ++j) + { + if (*j == *i) + { + result = false; + } + } + if (result) + { + prec.push_back (*i); + } + } +} + +void +RoutingTableEntry::Invalidate (Time badLinkLifetime) +{ + NS_LOG_FUNCTION (this << badLinkLifetime.As (Time::S)); + if (m_flag == INVALID) + { + return; + } + m_flag = INVALID; + m_reqCount = 0; + m_lifeTime = badLinkLifetime + Simulator::Now (); +} + +void +RoutingTableEntry::Print (Ptr<OutputStreamWrapper> stream, Time::Unit unit /* = Time::S */) const +{ + std::ostream* os = stream->GetStream (); + // Copy the current ostream state + std::ios oldState (nullptr); + oldState.copyfmt (*os); + + *os << std::resetiosflags (std::ios::adjustfield) << std::setiosflags (std::ios::left); + + std::ostringstream dest, gw, iface, expire; + dest << m_ipv4Route->GetDestination (); + gw << m_ipv4Route->GetGateway (); + iface << m_iface.GetLocal (); + expire << std::setprecision (2) << (m_lifeTime - Simulator::Now ()).As (unit); + *os << std::setw (16) << dest.str(); + *os << std::setw (16) << gw.str(); + *os << std::setw (16) << iface.str(); + *os << std::setw (16); + switch (m_flag) + { + case VALID: + { + *os << "UP"; + break; + } + case INVALID: + { + *os << "DOWN"; + break; + } + case IN_SEARCH: + { + *os << "IN_SEARCH"; + break; + } + } + + *os << std::setw (16) << expire.str(); + *os << m_hops << std::endl; + // Restore the previous ostream state + (*os).copyfmt (oldState); +} + +/* + The Routing Table + */ + +RoutingTable::RoutingTable (Time t) + : m_badLinkLifetime (t), + m_StoreRoutesTimer (Timer::CANCEL_ON_DESTROY), + routePointer(0), + encounterRate(10), + routeStorageFull(false) +{ + m_StoreRoutesTimer.SetFunction (&RoutingTable::StoreRoutes, this); + m_StoreRoutesTimer.Schedule (Seconds (3)); +} + +void RoutingTable::StoreRoutes() { + NS_LOG_INFO("Routing Table Timer is Working!"); + std::map<Ipv4Address, RoutingTableEntry> table = m_ipv4AddressEntry; + Purge (table); + + if(!routeStorageFull) { + RouteStorage.push_back(table); + routePointer++; + if(routePointer == encounterRate) routeStorageFull = true; + } + else + { + RouteStorage[routePointer] = table; + } + routePointer = routePointer % encounterRate; + float myAER = 0.0; + int result = GetAER(myAER); + + std::stringstream ss; + ss << "AER is: " << myAER << " result was: " << result; + NS_LOG_ERROR(ss.str()); + m_StoreRoutesTimer.Schedule (Seconds (1)); +} + +int +RoutingTable::GetAER(float &averageAER) +{ + // if we havent filled up the buffer yet, we can't calculate an AER value. + if(!routeStorageFull) + return 1; + + std::map<Ipv4Address, RoutingTableEntry> tableEntryNow = RouteStorage[routePointer]; + std::map<Ipv4Address, RoutingTableEntry> tableEntryPrev = RouteStorage[routePointer + 1]; + std::vector<uint32_t> encountersNow; + std::vector<uint32_t> encountersPrev; + + // Get the currently encountered node IDS + for(std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = + tableEntryNow.begin (); i != tableEntryNow.end (); ++i){ + uint8_t buf[4]; + i->second.GetNextHop().Serialize(buf); + encountersNow.push_back (unsigned(buf[3]) - 1); + } + + // Get the Previously encountered node IDs + for(std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = + tableEntryPrev.begin (); i != tableEntryPrev.end (); ++i){ + uint8_t buf[4]; + i->second.GetNextHop().Serialize(buf); + encountersPrev.push_back (unsigned(buf[3]) - 1); + } + + // make sure there are no duplicates within each encounter set: + std::set<uint32_t> s1( encountersNow.begin(), encountersNow.end() ); + std::set<uint32_t> s2( encountersPrev.begin(), encountersPrev.end() ); + encountersNow.assign( s1.begin(), s1.end() ); + encountersPrev.assign( s2.begin(), s2.end() ); + + // Now find the intersect of the two list. + std::vector<uint32_t> intersected_set; + + std::sort(encountersNow.begin(), encountersNow.end()); + std::sort(encountersPrev.begin(), encountersPrev.end()); + + std::set_intersection(encountersNow.begin(),encountersNow.end(), + encountersPrev.begin(),encountersPrev.end(), + back_inserter(intersected_set)); + uint32_t newEncounters = encountersNow.size() + encountersPrev.size() - (intersected_set.size()*2); + averageAER = (float)newEncounters / (float)encounterRate; + + //fix AER to 1.0 + averageAER = std::min(averageAER, (float)1.0); + + return 0; +} + +bool +RoutingTable::LookupRoute (Ipv4Address id, RoutingTableEntry & rt) +{ + NS_LOG_FUNCTION (this << id); + Purge (); + if (m_ipv4AddressEntry.empty ()) + { + NS_LOG_LOGIC ("Route to " << id << " not found; m_ipv4AddressEntry is empty"); + return false; + } + std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = + m_ipv4AddressEntry.find (id); + if (i == m_ipv4AddressEntry.end ()) + { + NS_LOG_LOGIC ("Route to " << id << " not found"); + return false; + } + rt = i->second; + NS_LOG_LOGIC ("Route to " << id << " found"); + return true; +} + +bool +RoutingTable::LookupValidRoute (Ipv4Address id, RoutingTableEntry & rt) +{ + NS_LOG_FUNCTION (this << id); + if (!LookupRoute (id, rt)) + { + NS_LOG_LOGIC ("Route to " << id << " not found"); + return false; + } + NS_LOG_LOGIC ("Route to " << id << " flag is " << ((rt.GetFlag () == VALID) ? "valid" : "not valid")); + return (rt.GetFlag () == VALID); +} + +bool +RoutingTable::DeleteRoute (Ipv4Address dst) +{ + NS_LOG_FUNCTION (this << dst); + Purge (); + if (m_ipv4AddressEntry.erase (dst) != 0) + { + NS_LOG_LOGIC ("Route deletion to " << dst << " successful"); + return true; + } + NS_LOG_LOGIC ("Route deletion to " << dst << " not successful"); + return false; +} + +bool +RoutingTable::AddRoute (RoutingTableEntry & rt) +{ + NS_LOG_FUNCTION (this); + Purge (); + if (rt.GetFlag () != IN_SEARCH) + { + rt.SetRreqCnt (0); + } + std::pair<std::map<Ipv4Address, RoutingTableEntry>::iterator, bool> result = + m_ipv4AddressEntry.insert (std::make_pair (rt.GetDestination (), rt)); + return result.second; +} + +bool +RoutingTable::Update (RoutingTableEntry & rt) +{ + NS_LOG_FUNCTION (this); + std::map<Ipv4Address, RoutingTableEntry>::iterator i = + m_ipv4AddressEntry.find (rt.GetDestination ()); + if (i == m_ipv4AddressEntry.end ()) + { + NS_LOG_LOGIC ("Route update to " << rt.GetDestination () << " fails; not found"); + return false; + } + i->second = rt; + if (i->second.GetFlag () != IN_SEARCH) + { + NS_LOG_LOGIC ("Route update to " << rt.GetDestination () << " set RreqCnt to 0"); + i->second.SetRreqCnt (0); + } + return true; +} + +bool +RoutingTable::SetEntryState (Ipv4Address id, RouteFlags state) +{ + NS_LOG_FUNCTION (this); + std::map<Ipv4Address, RoutingTableEntry>::iterator i = + m_ipv4AddressEntry.find (id); + if (i == m_ipv4AddressEntry.end ()) + { + NS_LOG_LOGIC ("Route set entry state to " << id << " fails; not found"); + return false; + } + i->second.SetFlag (state); + i->second.SetRreqCnt (0); + NS_LOG_LOGIC ("Route set entry state to " << id << ": new state is " << state); + return true; +} + +void +RoutingTable::GetListOfDestinationWithNextHop (Ipv4Address nextHop, std::map<Ipv4Address, uint32_t> & unreachable ) +{ + NS_LOG_FUNCTION (this); + Purge (); + unreachable.clear (); + for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = + m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end (); ++i) + { + if (i->second.GetNextHop () == nextHop) + { + NS_LOG_LOGIC ("Unreachable insert " << i->first << " " << i->second.GetSeqNo ()); + unreachable.insert (std::make_pair (i->first, i->second.GetSeqNo ())); + } + } +} + +void +RoutingTable::InvalidateRoutesWithDst (const std::map<Ipv4Address, uint32_t> & unreachable) +{ + NS_LOG_FUNCTION (this); + Purge (); + for (std::map<Ipv4Address, RoutingTableEntry>::iterator i = + m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end (); ++i) + { + for (std::map<Ipv4Address, uint32_t>::const_iterator j = + unreachable.begin (); j != unreachable.end (); ++j) + { + if ((i->first == j->first) && (i->second.GetFlag () == VALID)) + { + NS_LOG_LOGIC ("Invalidate route with destination address " << i->first); + i->second.Invalidate (m_badLinkLifetime); + } + } + } +} + +void +RoutingTable::DeleteAllRoutesFromInterface (Ipv4InterfaceAddress iface) +{ + NS_LOG_FUNCTION (this); + if (m_ipv4AddressEntry.empty ()) + { + return; + } + for (std::map<Ipv4Address, RoutingTableEntry>::iterator i = + m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end (); ) + { + if (i->second.GetInterface () == iface) + { + std::map<Ipv4Address, RoutingTableEntry>::iterator tmp = i; + ++i; + m_ipv4AddressEntry.erase (tmp); + } + else + { + ++i; + } + } +} + +void +RoutingTable::Purge () +{ + NS_LOG_FUNCTION (this); + if (m_ipv4AddressEntry.empty ()) + { + return; + } + for (std::map<Ipv4Address, RoutingTableEntry>::iterator i = + m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end (); ) + { + if (i->second.GetLifeTime () < Seconds (0)) + { + if (i->second.GetFlag () == INVALID) + { + std::map<Ipv4Address, RoutingTableEntry>::iterator tmp = i; + ++i; + m_ipv4AddressEntry.erase (tmp); + } + else if (i->second.GetFlag () == VALID) + { + NS_LOG_LOGIC ("Invalidate route with destination address " << i->first); + i->second.Invalidate (m_badLinkLifetime); + ++i; + } + else + { + ++i; + } + } + else + { + ++i; + } + } +} + +void +RoutingTable::Purge (std::map<Ipv4Address, RoutingTableEntry> &table) const +{ + NS_LOG_FUNCTION (this); + if (table.empty ()) + { + return; + } + for (std::map<Ipv4Address, RoutingTableEntry>::iterator i = + table.begin (); i != table.end (); ) + { + if (i->second.GetLifeTime () < Seconds (0)) + { + if (i->second.GetFlag () == INVALID) + { + std::map<Ipv4Address, RoutingTableEntry>::iterator tmp = i; + ++i; + table.erase (tmp); + } + else if (i->second.GetFlag () == VALID) + { + NS_LOG_LOGIC ("Invalidate route with destination address " << i->first); + i->second.Invalidate (m_badLinkLifetime); + ++i; + } + else + { + ++i; + } + } + else + { + ++i; + } + } +} + +bool +RoutingTable::MarkLinkAsUnidirectional (Ipv4Address neighbor, Time blacklistTimeout) +{ + NS_LOG_FUNCTION (this << neighbor << blacklistTimeout.As (Time::S)); + std::map<Ipv4Address, RoutingTableEntry>::iterator i = + m_ipv4AddressEntry.find (neighbor); + if (i == m_ipv4AddressEntry.end ()) + { + NS_LOG_LOGIC ("Mark link unidirectional to " << neighbor << " fails; not found"); + return false; + } + i->second.SetUnidirectional (true); + i->second.SetBlacklistTimeout (blacklistTimeout); + i->second.SetRreqCnt (0); + NS_LOG_LOGIC ("Set link to " << neighbor << " to unidirectional"); + return true; +} + +void +RoutingTable::Print (Ptr<OutputStreamWrapper> stream, Time::Unit unit /* = Time::S */) const +{ + std::map<Ipv4Address, RoutingTableEntry> table = m_ipv4AddressEntry; + Purge (table); + std::ostream* os = stream->GetStream (); + // Copy the current ostream state + std::ios oldState (nullptr); + oldState.copyfmt (*os); + + *os << std::resetiosflags (std::ios::adjustfield) << std::setiosflags (std::ios::left); + *os << "\nAODV Routing table\n"; + *os << std::setw (16) << "Destination"; + *os << std::setw (16) << "Gateway"; + *os << std::setw (16) << "Interface"; + *os << std::setw (16) << "Flag"; + *os << std::setw (16) << "Expire"; + *os << "Hops" << std::endl; + for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = + table.begin (); i != table.end (); ++i) + { + i->second.Print (stream, unit); + } + *stream->GetStream () << "\n"; +} + +} +} diff --git a/greyattack-module/model/greyattack-aodv-rtable.h b/greyattack-module/model/greyattack-aodv-rtable.h new file mode 100644 index 0000000000000000000000000000000000000000..6dc1c3cc907018979625f86b65631c4819a8d567 --- /dev/null +++ b/greyattack-module/model/greyattack-aodv-rtable.h @@ -0,0 +1,527 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based on + * NS-3 greyattack + * + * Authors: Charles Hutchins + */ +#ifndef greyattack_aodv_RTABLE_H +#define greyattack_aodv_RTABLE_H + +#include <stdint.h> +#include <cassert> +#include <map> +#include <sys/types.h> +#include "ns3/ipv4.h" +#include "ns3/ipv4-route.h" +#include "ns3/timer.h" +#include "ns3/net-device.h" +#include "ns3/output-stream-wrapper.h" + +namespace ns3 { +namespace greyattackAodv { + +/** + * \ingroup greyattack + * \brief Route record states + */ +enum RouteFlags +{ + VALID = 0, //!< VALID + INVALID = 1, //!< INVALID + IN_SEARCH = 2, //!< IN_SEARCH +}; + +/** + * \ingroup greyattack + * \brief Routing table entry + */ +class RoutingTableEntry +{ +public: + /** + * constructor + * + * \param dev the device + * \param dst the destination IP address + * \param vSeqNo verify sequence number flag + * \param seqNo the sequence number + * \param iface the interface + * \param hops the number of hops + * \param nextHop the IP address of the next hop + * \param lifetime the lifetime of the entry + * \param interaction the number of iteractions with this node + */ + RoutingTableEntry (Ptr<NetDevice> dev = 0,Ipv4Address dst = Ipv4Address (), bool vSeqNo = false, uint32_t seqNo = 0, + Ipv4InterfaceAddress iface = Ipv4InterfaceAddress (), uint16_t hops = 0, + Ipv4Address nextHop = Ipv4Address (), Time lifetime = Simulator::Now ()); + + ~RoutingTableEntry (); + + ///\name Precursors management + //\{ + /** + * Insert precursor in precursor list if it doesn't yet exist in the list + * \param id precursor address + * \return true on success + */ + bool InsertPrecursor (Ipv4Address id); + /** + * Lookup precursor by address + * \param id precursor address + * \return true on success + */ + bool LookupPrecursor (Ipv4Address id); + /** + * \brief Delete precursor + * \param id precursor address + * \return true on success + */ + bool DeletePrecursor (Ipv4Address id); + /// Delete all precursors + void DeleteAllPrecursors (); + /** + * Check that precursor list is empty + * \return true if precursor list is empty + */ + bool IsPrecursorListEmpty () const; + /** + * Inserts precursors in output parameter prec if they do not yet exist in vector + * \param prec vector of precursor addresses + */ + void GetPrecursors (std::vector<Ipv4Address> & prec) const; + //\} + + /** + * Mark entry as "down" (i.e. disable it) + * \param badLinkLifetime duration to keep entry marked as invalid + */ + void Invalidate (Time badLinkLifetime); + + // Fields + /** + * Get destination address function + * \returns the IPv4 destination address + */ + Ipv4Address GetDestination () const + { + return m_ipv4Route->GetDestination (); + } + /** + * Get route function + * \returns The IPv4 route + */ + Ptr<Ipv4Route> GetRoute () const + { + return m_ipv4Route; + } + /** + * Set route function + * \param r the IPv4 route + */ + void SetRoute (Ptr<Ipv4Route> r) + { + m_ipv4Route = r; + } + /** + * Set next hop address + * \param nextHop the next hop IPv4 address + */ + void SetNextHop (Ipv4Address nextHop) + { + m_ipv4Route->SetGateway (nextHop); + } + /** + * Get next hop address + * \returns the next hop address + */ + Ipv4Address GetNextHop () const + { + return m_ipv4Route->GetGateway (); + } + /** + * Set output device + * \param dev The output device + */ + void SetOutputDevice (Ptr<NetDevice> dev) + { + m_ipv4Route->SetOutputDevice (dev); + } + /** + * Get output device + * \returns the output device + */ + Ptr<NetDevice> GetOutputDevice () const + { + return m_ipv4Route->GetOutputDevice (); + } + /** + * Get the Ipv4InterfaceAddress + * \returns the Ipv4InterfaceAddress + */ + Ipv4InterfaceAddress GetInterface () const + { + return m_iface; + } + /** + * Set the Ipv4InterfaceAddress + * \param iface The Ipv4InterfaceAddress + */ + void SetInterface (Ipv4InterfaceAddress iface) + { + m_iface = iface; + } + /** + * Set the valid sequence number + * \param s the sequence number + */ + void SetValidSeqNo (bool s) + { + m_validSeqNo = s; + } + /** + * Get the valid sequence number + * \returns the valid sequence number + */ + bool GetValidSeqNo () const + { + return m_validSeqNo; + } + /** + * Set the sequence number + * \param sn the sequence number + */ + void SetSeqNo (uint32_t sn) + { + m_seqNo = sn; + } + /** + * Get the sequence number + * \returns the sequence number + */ + uint32_t GetSeqNo () const + { + return m_seqNo; + } + /** + * Set the number of hops + * \param hop the number of hops + */ + void SetHop (uint16_t hop) + { + m_hops = hop; + } + /** + * Get the number of hops + * \returns the number of hops + */ + uint16_t GetHop () const + { + return m_hops; + } + /** + * Set the lifetime + * \param lt The lifetime + */ + void SetLifeTime (Time lt) + { + m_lifeTime = lt + Simulator::Now (); + } + /** + * Get the lifetime + * \returns the lifetime + */ + Time GetLifeTime () const + { + return m_lifeTime - Simulator::Now (); + } + /** + * Set the route flags + * \param flag the route flags + */ + void SetFlag (RouteFlags flag) + { + m_flag = flag; + } + /** + * Get the route flags + * \returns the route flags + */ + RouteFlags GetFlag () const + { + return m_flag; + } + /** + * Set the RREQ count + * \param n the RREQ count + */ + void SetRreqCnt (uint8_t n) + { + m_reqCount = n; + } + /** + * Get the RREQ count + * \returns the RREQ count + */ + uint8_t GetRreqCnt () const + { + return m_reqCount; + } + /** + * Increment the RREQ count + */ + void IncrementRreqCnt () + { + m_reqCount++; + } + /** + * Set the unidirectional flag + * \param u the uni directional flag + */ + void SetUnidirectional (bool u) + { + m_blackListState = u; + } + /** + * Get the unidirectional flag + * \returns the unidirectional flag + */ + bool IsUnidirectional () const + { + return m_blackListState; + } + /** + * Set the blacklist timeout + * \param t the blacklist timeout value + */ + void SetBlacklistTimeout (Time t) + { + m_blackListTimeout = t; + } + /** + * Get the blacklist timeout value + * \returns the blacklist timeout value + */ + Time GetBlacklistTimeout () const + { + return m_blackListTimeout; + } + /// RREP_ACK timer + Timer m_ackTimer; + + /** + * \brief Compare destination address + * \param dst IP address to compare + * \return true if equal + */ + bool operator== (Ipv4Address const dst) const + { + return (m_ipv4Route->GetDestination () == dst); + } + /** + * Print packet to trace file + * \param stream The output stream + * \param unit The time unit to use (default Time::S) + */ + void Print (Ptr<OutputStreamWrapper> stream, Time::Unit unit = Time::S) const; + +private: + /// Valid Destination Sequence Number flag + bool m_validSeqNo; + /// Destination Sequence Number, if m_validSeqNo = true + uint32_t m_seqNo; + /// Hop Count (number of hops needed to reach destination) + uint16_t m_hops; + /** + * \brief Expiration or deletion time of the route + * Lifetime field in the routing table plays dual role: + * for an active route it is the expiration time, and for an invalid route + * it is the deletion time. + */ + Time m_lifeTime; + /** Ip route, include + * - destination address + * - source address + * - next hop address (gateway) + * - output device + */ + Ptr<Ipv4Route> m_ipv4Route; + /// Output interface address + Ipv4InterfaceAddress m_iface; + /// Routing flags: valid, invalid or in search + RouteFlags m_flag; + + /// List of precursors + std::vector<Ipv4Address> m_precursorList; + /// When I can send another request + Time m_routeRequestTimout; + /// Number of route requests + uint8_t m_reqCount; + /// Indicate if this entry is in "blacklist" + bool m_blackListState; + /// Time for which the node is put into the blacklist + Time m_blackListTimeout; +}; + +/** + * \ingroup greyattack + * \brief The Routing table used by greyattack protocol + */ +class RoutingTable +{ +public: + /** + * constructor + * \param t the routing table entry lifetime + */ + RoutingTable (Time t); + ///\name Handle lifetime of invalid route + //\{ + /** + * Get the lifetime of a bad link + * + * \return the lifetime of a bad link + */ + Time GetBadLinkLifetime () const + { + return m_badLinkLifetime; + } + /** + * Set the lifetime of a bad link + * + * \param t the lifetime of a bad link + */ + void SetBadLinkLifetime (Time t) + { + m_badLinkLifetime = t; + } + + + //\} + /** + * Add routing table entry if it doesn't yet exist in routing table + * \param r routing table entry + * \return true in success + */ + bool AddRoute (RoutingTableEntry & r); + /** + * Delete routing table entry with destination address dst, if it exists. + * \param dst destination address + * \return true on success + */ + bool DeleteRoute (Ipv4Address dst); + /** + * Lookup routing table entry with destination address dst + * \param dst destination address + * \param rt entry with destination address dst, if exists + * \return true on success + */ + bool LookupRoute (Ipv4Address dst, RoutingTableEntry & rt); + /** + * Lookup route in VALID state + * \param dst destination address + * \param rt entry with destination address dst, if exists + * \return true on success + */ + bool LookupValidRoute (Ipv4Address dst, RoutingTableEntry & rt); + /** + * Update routing table + * \param rt entry with destination address dst, if exists + * \return true on success + */ + bool Update (RoutingTableEntry & rt); + /** + * Set routing table entry flags + * \param dst destination address + * \param state the routing flags + * \return true on success + */ + bool SetEntryState (Ipv4Address dst, RouteFlags state); + /** + * Lookup routing entries with next hop Address dst and not empty list of precursors. + * + * \param nextHop the next hop IP address + * \param unreachable + */ + void GetListOfDestinationWithNextHop (Ipv4Address nextHop, std::map<Ipv4Address, uint32_t> & unreachable); + /** + * Update routing entries with this destination as follows: + * 1. The destination sequence number of this routing entry, if it + * exists and is valid, is incremented. + * 2. The entry is invalidated by marking the route entry as invalid + * 3. The Lifetime field is updated to current time plus DELETE_PERIOD. + * \param unreachable routes to invalidate + */ + void InvalidateRoutesWithDst (std::map<Ipv4Address, uint32_t> const & unreachable); + /** + * Delete all route from interface with address iface + * \param iface the interface IP address + */ + void DeleteAllRoutesFromInterface (Ipv4InterfaceAddress iface); + /// Delete all entries from routing table + void Clear () + { + m_ipv4AddressEntry.clear (); + } + /// Delete all outdated entries and invalidate valid entry if Lifetime is expired + void Purge (); + /** Mark entry as unidirectional (e.g. add this neighbor to "blacklist" for blacklistTimeout period) + * \param neighbor - neighbor address link to which assumed to be unidirectional + * \param blacklistTimeout - time for which the neighboring node is put into the blacklist + * \return true on success + */ + bool MarkLinkAsUnidirectional (Ipv4Address neighbor, Time blacklistTimeout); + /** + * Print routing table + * \param stream the output stream + * \param unit The time unit to use (default Time::S) + */ + void Print (Ptr<OutputStreamWrapper> stream, Time::Unit unit = Time::S) const; + + /** + * + * @param averageAER - the average encounter rate + * @return - 1 on error (such as the buffer is not big enough yet to caluclate a value) and 0 for success + */ + int GetAER(float &averageAER); + +private: + /// The routing table + std::map<Ipv4Address, RoutingTableEntry> m_ipv4AddressEntry; + /// Deletion time for invalid routes + Time m_badLinkLifetime; + // Timer used to store the route table every second or so. + Timer m_StoreRoutesTimer; + // vector to store the routes + std::vector<std::map<Ipv4Address, RoutingTableEntry>> RouteStorage; + uint32_t routePointer; + uint32_t encounterRate; + bool routeStorageFull; + /** + * const version of Purge, for use by Print() method + * \param table the routing table entry to purge + */ + void Purge (std::map<Ipv4Address, RoutingTableEntry> &table) const; + + void StoreRoutes(); +}; + +} // namespace greyattack-aodv +} // namespace ns3 + +#endif /* greyattack_aodv_RTABLE_H */ diff --git a/greyattack-module/model/greyattack-aodv.cc b/greyattack-module/model/greyattack-aodv.cc new file mode 100644 index 0000000000000000000000000000000000000000..95b48aa32240da0162db0a4749a2ada215f41225 --- /dev/null +++ b/greyattack-module/model/greyattack-aodv.cc @@ -0,0 +1,14 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ + +#include "greyattack-aodv.h" + +namespace ns3 { + +/* ... */ + +namespace greyattackAodv{ + +} + + +} \ No newline at end of file diff --git a/greyattack-module/model/greyattack-aodv.h b/greyattack-module/model/greyattack-aodv.h new file mode 100644 index 0000000000000000000000000000000000000000..81238ce11940dbc87bb36cb21bb57241d99b1aae --- /dev/null +++ b/greyattack-module/model/greyattack-aodv.h @@ -0,0 +1,11 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +#ifndef GREYATTACK_AODV_H +#define GREYATTACK_AODV_H + +namespace ns3 { + +/* ... */ + +} + +#endif /* GREYATTACK_AODV_H */ diff --git a/greyattack-module/test/examples-to-run.py b/greyattack-module/test/examples-to-run.py new file mode 100644 index 0000000000000000000000000000000000000000..4ffeed82bfded5492ba11ddc901f60d13e33ae39 --- /dev/null +++ b/greyattack-module/test/examples-to-run.py @@ -0,0 +1,20 @@ +#! /usr/bin/env python3 +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + +# A list of C++ examples to run in order to ensure that they remain +# buildable and runnable over time. Each tuple in the list contains +# +# (example_name, do_run, do_valgrind_run). +# +# See test.py for more information. +cpp_examples = [ + ("aodvKmeans", "True", "True"), +] + +# A list of Python examples to run in order to ensure that they remain +# runnable over time. Each tuple in the list contains +# +# (example_name, do_run). +# +# See test.py for more information. +python_examples = [] diff --git a/greyattack-module/test/greyattack-aodv-id-cache-test-suite.cc b/greyattack-module/test/greyattack-aodv-id-cache-test-suite.cc new file mode 100644 index 0000000000000000000000000000000000000000..0e11ea4706abca972ca86bd3681794164be033c4 --- /dev/null +++ b/greyattack-module/test/greyattack-aodv-id-cache-test-suite.cc @@ -0,0 +1,119 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based on + * NS-2 greyattack model developed by + * + * Authors: Charles Hutchins + */ +#include "ns3/greyattack-aodv-id-cache.h" +#include "ns3/test.h" + +namespace ns3 { +namespace greyattackAodv { + +/** + * \ingroup greyattack + * \defgroup greyattack-test greyattack module tests + */ + + +/** + * \ingroup greyattack-test + * \ingroup tests + * + * \brief Unit test for id cache + */ +class IdCacheTest : public TestCase +{ +public: + IdCacheTest () : TestCase ("Id Cache"), + cache (Seconds (10)) + { + } + virtual void DoRun (); + +private: + /// Timeout test function #1 + void CheckTimeout1 (); + /// Timeout test function #2 + void CheckTimeout2 (); + /// Timeout test function #3 + void CheckTimeout3 (); + + /// ID cache + IdCache cache; +}; + +void +IdCacheTest::DoRun () +{ + NS_TEST_EXPECT_MSG_EQ (cache.GetLifeTime (), Seconds (10), "Lifetime"); + NS_TEST_EXPECT_MSG_EQ (cache.IsDuplicate (Ipv4Address ("1.2.3.4"), 3), false, "Unknown ID & address"); + NS_TEST_EXPECT_MSG_EQ (cache.IsDuplicate (Ipv4Address ("1.2.3.4"), 4), false, "Unknown ID"); + NS_TEST_EXPECT_MSG_EQ (cache.IsDuplicate (Ipv4Address ("4.3.2.1"), 3), false, "Unknown address"); + NS_TEST_EXPECT_MSG_EQ (cache.IsDuplicate (Ipv4Address ("1.2.3.4"), 3), true, "Known address & ID"); + cache.SetLifetime (Seconds (15)); + NS_TEST_EXPECT_MSG_EQ (cache.GetLifeTime (), Seconds (15), "New lifetime"); + cache.IsDuplicate (Ipv4Address ("1.1.1.1"), 4); + cache.IsDuplicate (Ipv4Address ("1.1.1.1"), 4); + cache.IsDuplicate (Ipv4Address ("2.2.2.2"), 5); + cache.IsDuplicate (Ipv4Address ("3.3.3.3"), 6); + NS_TEST_EXPECT_MSG_EQ (cache.GetSize (), 6, "trivial"); + + Simulator::Schedule (Seconds (5), &IdCacheTest::CheckTimeout1, this); + Simulator::Schedule (Seconds (11), &IdCacheTest::CheckTimeout2, this); + Simulator::Schedule (Seconds (30), &IdCacheTest::CheckTimeout3, this); + Simulator::Run (); + Simulator::Destroy (); +} + +void +IdCacheTest::CheckTimeout1 () +{ + NS_TEST_EXPECT_MSG_EQ (cache.GetSize (), 6, "Nothing expire"); +} + +void +IdCacheTest::CheckTimeout2 () +{ + NS_TEST_EXPECT_MSG_EQ (cache.GetSize (), 3, "3 records left"); +} + +void +IdCacheTest::CheckTimeout3 () +{ + NS_TEST_EXPECT_MSG_EQ (cache.GetSize (), 0, "All records expire"); +} + +/** + * \ingroup greyattack-test + * \ingroup tests + * + * \brief Id Cache Test Suite + */ +class IdCacheTestSuite : public TestSuite +{ +public: + IdCacheTestSuite () : TestSuite ("greyattack-routing-id-cache", UNIT) + { + AddTestCase (new IdCacheTest, TestCase::QUICK); + } +} g_idCacheTestSuite; ///< the test suite + +} // namespace greyattack +} // namespace ns3 diff --git a/greyattack-module/test/greyattack-aodv-test-suite.cc b/greyattack-module/test/greyattack-aodv-test-suite.cc new file mode 100644 index 0000000000000000000000000000000000000000..7c00c33233200efcdd0e135263fe80582e7bd821 --- /dev/null +++ b/greyattack-module/test/greyattack-aodv-test-suite.cc @@ -0,0 +1,669 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Pavel Boyko <boyko@iitp.ru> + */ +#include "ns3/test.h" +#include "ns3/greyattack-aodv-neighbor.h" +#include "ns3/greyattack-aodv-packet.h" +#include "ns3/greyattack-aodv-rqueue.h" +#include "ns3/greyattack-aodv-rtable.h" +#include "ns3/ipv4-route.h" + +namespace ns3 { +namespace greyattackAodv { + +/** + * \ingroup greyattack-test + * \ingroup tests + * + * \brief Unit test for neighbors + */ +struct NeighborTest : public TestCase +{ + NeighborTest () : TestCase ("Neighbor"), + neighbor (0) + { + } + virtual void DoRun (); + /** + * Handler test function + * \param addr the IPv4 address of the neighbor + */ + void Handler (Ipv4Address addr); + /// Check timeout function 1 + void CheckTimeout1 (); + /// Check timeout function 2 + void CheckTimeout2 (); + /// Check timeout function 3 + void CheckTimeout3 (); + /// The Neighbors + Neighbors * neighbor; +}; + +void +NeighborTest::Handler (Ipv4Address addr) +{ +} + +void +NeighborTest::CheckTimeout1 () +{ + NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.2.3.4")), true, "Neighbor exists"); + NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.1.1.1")), true, "Neighbor exists"); + NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("2.2.2.2")), true, "Neighbor exists"); + NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("3.3.3.3")), true, "Neighbor exists"); +} +void +NeighborTest::CheckTimeout2 () +{ + NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.2.3.4")), false, "Neighbor doesn't exist"); + NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.1.1.1")), false, "Neighbor doesn't exist"); + NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("2.2.2.2")), false, "Neighbor doesn't exist"); + NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("3.3.3.3")), true, "Neighbor exists"); +} +void +NeighborTest::CheckTimeout3 () +{ + NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.2.3.4")), false, "Neighbor doesn't exist"); + NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.1.1.1")), false, "Neighbor doesn't exist"); + NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("2.2.2.2")), false, "Neighbor doesn't exist"); + NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("3.3.3.3")), false, "Neighbor doesn't exist"); +} + +void +NeighborTest::DoRun () +{ + Neighbors nb (Seconds (1)); + neighbor = &nb; + neighbor->SetCallback (MakeCallback (&NeighborTest::Handler, this)); + neighbor->Update (Ipv4Address ("1.2.3.4"), Seconds (1)); + NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.2.3.4")), true, "Neighbor exists"); + NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("4.3.2.1")), false, "Neighbor doesn't exist"); + neighbor->Update (Ipv4Address ("1.2.3.4"), Seconds (10)); + NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.2.3.4")), true, "Neighbor exists"); + NS_TEST_EXPECT_MSG_EQ (neighbor->GetExpireTime (Ipv4Address ("1.2.3.4")), Seconds (10), "Known expire time"); + NS_TEST_EXPECT_MSG_EQ (neighbor->GetExpireTime (Ipv4Address ("4.3.2.1")), Seconds (0), "Known expire time"); + neighbor->Update (Ipv4Address ("1.1.1.1"), Seconds (5)); + neighbor->Update (Ipv4Address ("2.2.2.2"), Seconds (10)); + neighbor->Update (Ipv4Address ("3.3.3.3"), Seconds (20)); + + Simulator::Schedule (Seconds (2), &NeighborTest::CheckTimeout1, this); + Simulator::Schedule (Seconds (15), &NeighborTest::CheckTimeout2, this); + Simulator::Schedule (Seconds (30), &NeighborTest::CheckTimeout3, this); + Simulator::Run (); + Simulator::Destroy (); +} + +/** + * \ingroup greyattack-test + * \ingroup tests + * + * \brief Type header test case + */ +struct TypeHeaderTest : public TestCase +{ + TypeHeaderTest () : TestCase ("greyattack TypeHeader") + { + } + virtual void DoRun () + { + TypeHeader h (greyattackTYPE_RREQ); + NS_TEST_EXPECT_MSG_EQ (h.IsValid (), true, "Default header is valid"); + NS_TEST_EXPECT_MSG_EQ (h.Get (), greyattackTYPE_RREQ, "Default header is RREQ"); + + Ptr<Packet> p = Create<Packet> (); + p->AddHeader (h); + TypeHeader h2 (greyattackTYPE_RREP); + uint32_t bytes = p->RemoveHeader (h2); + NS_TEST_EXPECT_MSG_EQ (bytes, 1, "Type header is 1 byte long"); + NS_TEST_EXPECT_MSG_EQ (h, h2, "Round trip serialization works"); + } +}; + +/** + * \ingroup greyattack-test + * \ingroup tests + * + * \brief Unit test for RREQ + */ +struct RreqHeaderTest : public TestCase +{ + RreqHeaderTest () : TestCase ("greyattack RREQ") + { + } + virtual void DoRun () + { + RreqHeader h (/*flags*/ 0, /*reserved*/ 0, /*hopCount*/ 6, /*requestID*/ 1, /*dst*/ Ipv4Address ("1.2.3.4"), + /*dstSeqNo*/ 40, /*origin*/ Ipv4Address ("4.3.2.1"), /*originSeqNo*/ 10); + NS_TEST_EXPECT_MSG_EQ (h.GetGratuitousRrep (), false, "trivial"); + NS_TEST_EXPECT_MSG_EQ (h.GetDestinationOnly (), false, "trivial"); + NS_TEST_EXPECT_MSG_EQ (h.GetHopCount (), 6, "trivial"); + NS_TEST_EXPECT_MSG_EQ (h.GetId (), 1, "trivial"); + NS_TEST_EXPECT_MSG_EQ (h.GetDst (), Ipv4Address ("1.2.3.4"), "trivial"); + NS_TEST_EXPECT_MSG_EQ (h.GetDstSeqno (), 40, "trivial"); + NS_TEST_EXPECT_MSG_EQ (h.GetOrigin (), Ipv4Address ("4.3.2.1"), "trivial"); + NS_TEST_EXPECT_MSG_EQ (h.GetOriginSeqno (), 10, "trivial"); + + h.SetGratuitousRrep (true); + NS_TEST_EXPECT_MSG_EQ (h.GetGratuitousRrep (), true, "trivial"); + h.SetDestinationOnly (true); + NS_TEST_EXPECT_MSG_EQ (h.GetDestinationOnly (), true, "trivial"); + h.SetUnknownSeqno (true); + NS_TEST_EXPECT_MSG_EQ (h.GetUnknownSeqno (), true, "trivial"); + h.SetDst (Ipv4Address ("1.1.1.1")); + NS_TEST_EXPECT_MSG_EQ (h.GetDst (), Ipv4Address ("1.1.1.1"), "trivial"); + h.SetDstSeqno (5); + NS_TEST_EXPECT_MSG_EQ (h.GetDstSeqno (), 5, "trivial"); + h.SetHopCount (7); + NS_TEST_EXPECT_MSG_EQ (h.GetHopCount (), 7, "trivial"); + h.SetId (55); + NS_TEST_EXPECT_MSG_EQ (h.GetId (), 55, "trivial"); + h.SetOrigin (Ipv4Address ("4.4.4.4")); + NS_TEST_EXPECT_MSG_EQ (h.GetOrigin (), Ipv4Address ("4.4.4.4"), "trivial"); + h.SetOriginSeqno (23); + NS_TEST_EXPECT_MSG_EQ (h.GetOriginSeqno (), 23, "trivial"); + + Ptr<Packet> p = Create<Packet> (); + p->AddHeader (h); + RreqHeader h2; + uint32_t bytes = p->RemoveHeader (h2); + NS_TEST_EXPECT_MSG_EQ (bytes, 23, "RREP is 23 bytes long"); + NS_TEST_EXPECT_MSG_EQ (h, h2, "Round trip serialization works"); + + } +}; + +/** + * \ingroup greyattack-test + * \ingroup tests + * + * \brief Unit test for RREP + */ +struct RrepHeaderTest : public TestCase +{ + RrepHeaderTest () : TestCase ("greyattack RREP") + { + } + virtual void DoRun () + { + RrepHeader h (/*prefixSize*/ 0, /*hopCount*/ 12, /*dst*/ Ipv4Address ("1.2.3.4"), /*dstSeqNo*/ 2, + /*origin*/ Ipv4Address ("4.3.2.1"), /*lifetime*/ Seconds (3)); + NS_TEST_EXPECT_MSG_EQ (h.GetPrefixSize (), 0, "trivial"); + NS_TEST_EXPECT_MSG_EQ (h.GetHopCount (), 12, "trivial"); + NS_TEST_EXPECT_MSG_EQ (h.GetDst (), Ipv4Address ("1.2.3.4"), "trivial"); + NS_TEST_EXPECT_MSG_EQ (h.GetDstSeqno (), 2, "trivial"); + NS_TEST_EXPECT_MSG_EQ (h.GetOrigin (), Ipv4Address ("4.3.2.1"), "trivial"); + NS_TEST_EXPECT_MSG_EQ (h.GetLifeTime (), Seconds (3), "trivial"); + h.SetDst (Ipv4Address ("1.1.1.1")); + NS_TEST_EXPECT_MSG_EQ (h.GetDst (), Ipv4Address ("1.1.1.1"), "trivial"); + h.SetDstSeqno (123); + NS_TEST_EXPECT_MSG_EQ (h.GetDstSeqno (), 123, "trivial"); + h.SetOrigin (Ipv4Address ("4.4.4.4")); + NS_TEST_EXPECT_MSG_EQ (h.GetOrigin (), Ipv4Address ("4.4.4.4"), "trivial"); + h.SetLifeTime (MilliSeconds (1200)); + NS_TEST_EXPECT_MSG_EQ (h.GetLifeTime (), MilliSeconds (1200), "trivial"); + h.SetAckRequired (true); + NS_TEST_EXPECT_MSG_EQ (h.GetAckRequired (), true, "trivial"); + h.SetAckRequired (false); + NS_TEST_EXPECT_MSG_EQ (h.GetAckRequired (), false, "trivial"); + h.SetPrefixSize (2); + NS_TEST_EXPECT_MSG_EQ (h.GetPrefixSize (), 2, "trivial"); + h.SetHopCount (15); + NS_TEST_EXPECT_MSG_EQ (h.GetHopCount (), 15, "trivial"); + + h.SetHello (Ipv4Address ("10.0.0.2"), 9, Seconds (15)); + NS_TEST_EXPECT_MSG_EQ (h.GetDst (), h.GetOrigin (), "trivial"); + NS_TEST_EXPECT_MSG_EQ (h.GetDstSeqno (), 9, "trivial"); + NS_TEST_EXPECT_MSG_EQ (h.GetLifeTime (), Seconds (15), "trivial"); + + Ptr<Packet> p = Create<Packet> (); + p->AddHeader (h); + RrepHeader h2; + uint32_t bytes = p->RemoveHeader (h2); + NS_TEST_EXPECT_MSG_EQ (bytes, 19, "RREP is 19 bytes long"); + NS_TEST_EXPECT_MSG_EQ (h, h2, "Round trip serialization works"); + } +}; + +/** + * \ingroup greyattack-test + * \ingroup tests + * + * \brief Unit test for RREP-ACK + */ +struct RrepAckHeaderTest : public TestCase +{ + RrepAckHeaderTest () : TestCase ("greyattack RREP-ACK") + { + } + virtual void DoRun () + { + RrepAckHeader h; + Ptr<Packet> p = Create<Packet> (); + p->AddHeader (h); + RrepAckHeader h2; + uint32_t bytes = p->RemoveHeader (h2); + NS_TEST_EXPECT_MSG_EQ (bytes, 1, "ACK is 1 byte long"); + NS_TEST_EXPECT_MSG_EQ (h, h2, "Round trip serialization works"); + } +}; + +/** + * \ingroup greyattack-test + * \ingroup tests + * + * \brief Unit test for RERR + */ +struct RerrHeaderTest : public TestCase +{ + RerrHeaderTest () : TestCase ("greyattack RERR") + { + } + virtual void DoRun () + { + RerrHeader h; + h.SetNoDelete (true); + NS_TEST_EXPECT_MSG_EQ (h.GetNoDelete (), true, "trivial"); + Ipv4Address dst = Ipv4Address ("1.2.3.4"); + NS_TEST_EXPECT_MSG_EQ (h.AddUnDestination (dst, 12), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (h.GetDestCount (), 1, "trivial"); + NS_TEST_EXPECT_MSG_EQ (h.AddUnDestination (dst, 13), true, "trivial"); + Ipv4Address dst2 = Ipv4Address ("4.3.2.1"); + NS_TEST_EXPECT_MSG_EQ (h.AddUnDestination (dst2, 12), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (h.GetDestCount (), 2, "trivial"); + + Ptr<Packet> p = Create<Packet> (); + p->AddHeader (h); + RerrHeader h2; + uint32_t bytes = p->RemoveHeader (h2); + NS_TEST_EXPECT_MSG_EQ (bytes, h.GetSerializedSize (), "(De)Serialized size match"); + NS_TEST_EXPECT_MSG_EQ (h, h2, "Round trip serialization works"); + } +}; + +/** + * \ingroup greyattack-test + * \ingroup tests + * + * \brief Unit test for greyattack routing table entry + */ +struct QueueEntryTest : public TestCase +{ + QueueEntryTest () : TestCase ("QueueEntry") + { + } + /** + * Unicast test function + * \param route the IPv4 route + * \param packet the packet + * \param header the IPv4 header + */ + void Unicast (Ptr<Ipv4Route> route, Ptr<const Packet> packet, const Ipv4Header & header) + { + } + /** + * Error test function + * \param p The packet + * \param h The header + * \param e the socket error + */ + void Error (Ptr<const Packet> p, const Ipv4Header & h, Socket::SocketErrno e) + { + } + /** + * Unicast 2 testfunction + * \param route The IPv4 route + * \param packet The packet + * \param header The header + */ + void Unicast2 (Ptr<Ipv4Route> route, Ptr<const Packet> packet, const Ipv4Header & header) + { + } + /** + * Error2 test function + * \param p The packet + * \param h The header + * \param e the socket error + */ + void Error2 (Ptr<const Packet> p, const Ipv4Header & h, Socket::SocketErrno e) + { + } + virtual void DoRun () + { + Ptr<const Packet> packet = Create<Packet> (); + Ipv4Header h; + h.SetDestination (Ipv4Address ("1.2.3.4")); + h.SetSource (Ipv4Address ("4.3.2.1")); + Ipv4RoutingProtocol::UnicastForwardCallback ucb = MakeCallback (&QueueEntryTest::Unicast, this); + Ipv4RoutingProtocol::ErrorCallback ecb = MakeCallback (&QueueEntryTest::Error, this); + QueueEntry entry (packet, h, ucb, ecb, Seconds (1)); + NS_TEST_EXPECT_MSG_EQ (h.GetDestination (), entry.GetIpv4Header ().GetDestination (), "trivial"); + NS_TEST_EXPECT_MSG_EQ (h.GetSource (), entry.GetIpv4Header ().GetSource (), "trivial"); + NS_TEST_EXPECT_MSG_EQ (ucb.IsEqual (entry.GetUnicastForwardCallback ()), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (ecb.IsEqual (entry.GetErrorCallback ()), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (entry.GetExpireTime (), Seconds (1), "trivial"); + NS_TEST_EXPECT_MSG_EQ (entry.GetPacket (), packet, "trivial"); + entry.SetExpireTime (Seconds (3)); + NS_TEST_EXPECT_MSG_EQ (entry.GetExpireTime (), Seconds (3), "trivial"); + Ipv4Header h2; + h2.SetDestination (Ipv4Address ("1.1.1.1")); + entry.SetIpv4Header (h2); + NS_TEST_EXPECT_MSG_EQ (entry.GetIpv4Header ().GetDestination (), Ipv4Address ("1.1.1.1"), "trivial"); + Ipv4RoutingProtocol::UnicastForwardCallback ucb2 = MakeCallback (&QueueEntryTest::Unicast2, this); + Ipv4RoutingProtocol::ErrorCallback ecb2 = MakeCallback (&QueueEntryTest::Error2, this); + entry.SetErrorCallback (ecb2); + NS_TEST_EXPECT_MSG_EQ (ecb2.IsEqual (entry.GetErrorCallback ()), true, "trivial"); + entry.SetUnicastForwardCallback (ucb2); + NS_TEST_EXPECT_MSG_EQ (ucb2.IsEqual (entry.GetUnicastForwardCallback ()), true, "trivial"); + } +}; +//----------------------------------------------------------------------------- +/// Unit test for RequestQueue +struct greyattackRqueueTest : public TestCase +{ + greyattackRqueueTest () : TestCase ("Rqueue"), + q (64, Seconds (30)) + { + } + virtual void DoRun (); + /** + * Unicast test function + * \param route the IPv4 route + * \param packet the packet + * \param header the IPv4 header + */ + void Unicast (Ptr<Ipv4Route> route, Ptr<const Packet> packet, const Ipv4Header & header) + { + } + /** + * Error test function + * \param p The packet + * \param h The header + * \param e the socket error + */ + void Error (Ptr<const Packet> p, const Ipv4Header & h, Socket::SocketErrno e) + { + } + /// Check size limit function + void CheckSizeLimit (); + /// Check timeout function + void CheckTimeout (); + + /// Request queue + RequestQueue q; +}; + +void +greyattackRqueueTest::DoRun () +{ + NS_TEST_EXPECT_MSG_EQ (q.GetMaxQueueLen (), 64, "trivial"); + q.SetMaxQueueLen (32); + NS_TEST_EXPECT_MSG_EQ (q.GetMaxQueueLen (), 32, "trivial"); + NS_TEST_EXPECT_MSG_EQ (q.GetQueueTimeout (), Seconds (30), "trivial"); + q.SetQueueTimeout (Seconds (10)); + NS_TEST_EXPECT_MSG_EQ (q.GetQueueTimeout (), Seconds (10), "trivial"); + + Ptr<const Packet> packet = Create<Packet> (); + Ipv4Header h; + h.SetDestination (Ipv4Address ("1.2.3.4")); + h.SetSource (Ipv4Address ("4.3.2.1")); + Ipv4RoutingProtocol::UnicastForwardCallback ucb = MakeCallback (&greyattackRqueueTest::Unicast, this); + Ipv4RoutingProtocol::ErrorCallback ecb = MakeCallback (&greyattackRqueueTest::Error, this); + QueueEntry e1 (packet, h, ucb, ecb, Seconds (1)); + q.Enqueue (e1); + q.Enqueue (e1); + q.Enqueue (e1); + NS_TEST_EXPECT_MSG_EQ (q.Find (Ipv4Address ("1.2.3.4")), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (q.Find (Ipv4Address ("1.1.1.1")), false, "trivial"); + NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 1, "trivial"); + q.DropPacketWithDst (Ipv4Address ("1.2.3.4")); + NS_TEST_EXPECT_MSG_EQ (q.Find (Ipv4Address ("1.2.3.4")), false, "trivial"); + NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 0, "trivial"); + + h.SetDestination (Ipv4Address ("2.2.2.2")); + QueueEntry e2 (packet, h, ucb, ecb, Seconds (1)); + q.Enqueue (e1); + q.Enqueue (e2); + Ptr<Packet> packet2 = Create<Packet> (); + QueueEntry e3 (packet2, h, ucb, ecb, Seconds (1)); + NS_TEST_EXPECT_MSG_EQ (q.Dequeue (Ipv4Address ("3.3.3.3"), e3), false, "trivial"); + NS_TEST_EXPECT_MSG_EQ (q.Dequeue (Ipv4Address ("2.2.2.2"), e3), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (q.Find (Ipv4Address ("2.2.2.2")), false, "trivial"); + q.Enqueue (e2); + q.Enqueue (e3); + NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 2, "trivial"); + Ptr<Packet> packet4 = Create<Packet> (); + h.SetDestination (Ipv4Address ("1.2.3.4")); + QueueEntry e4 (packet4, h, ucb, ecb, Seconds (20)); + q.Enqueue (e4); + NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 3, "trivial"); + q.DropPacketWithDst (Ipv4Address ("1.2.3.4")); + NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 1, "trivial"); + + CheckSizeLimit (); + + Ipv4Header header2; + Ipv4Address dst2 ("1.2.3.4"); + header2.SetDestination (dst2); + + Simulator::Schedule (q.GetQueueTimeout () + Seconds (1), &greyattackRqueueTest::CheckTimeout, this); + + Simulator::Run (); + Simulator::Destroy (); +} + +void +greyattackRqueueTest::CheckSizeLimit () +{ + Ptr<Packet> packet = Create<Packet> (); + Ipv4Header header; + Ipv4RoutingProtocol::UnicastForwardCallback ucb = MakeCallback (&greyattackRqueueTest::Unicast, this); + Ipv4RoutingProtocol::ErrorCallback ecb = MakeCallback (&greyattackRqueueTest::Error, this); + QueueEntry e1 (packet, header, ucb, ecb, Seconds (1)); + + for (uint32_t i = 0; i < q.GetMaxQueueLen (); ++i) + { + q.Enqueue (e1); + } + NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 2, "trivial"); + + for (uint32_t i = 0; i < q.GetMaxQueueLen (); ++i) + { + q.Enqueue (e1); + } + NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 2, "trivial"); +} + +void +greyattackRqueueTest::CheckTimeout () +{ + NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 0, "Must be empty now"); +} + +/** + * \ingroup greyattack-test + * \ingroup tests + * + * \brief Unit test for greyattack routing table entry + */ +struct greyattackRtableEntryTest : public TestCase +{ + greyattackRtableEntryTest () : TestCase ("RtableEntry") + { + } + virtual void DoRun () + { + Ptr<NetDevice> dev; + Ipv4InterfaceAddress iface; + RoutingTableEntry rt (/*output device*/ dev, /*dst*/ Ipv4Address ("1.2.3.4"), /*validSeqNo*/ true, /*seqNo*/ 10, + /*interface*/ iface, /*hop*/ 5, /*next hop*/ Ipv4Address ("3.3.3.3"), /*lifetime*/ Seconds (10)); + NS_TEST_EXPECT_MSG_EQ (rt.GetOutputDevice (), dev, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.GetDestination (), Ipv4Address ("1.2.3.4"), "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.GetValidSeqNo (), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.GetSeqNo (), 10, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.GetInterface (), iface, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.GetHop (), 5, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.GetNextHop (), Ipv4Address ("3.3.3.3"), "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.GetLifeTime (), Seconds (10), "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.GetFlag (), VALID, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.GetRreqCnt (), 0, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.IsPrecursorListEmpty (), true, "trivial"); + + Ptr<NetDevice> dev2; + Ipv4InterfaceAddress iface2; + rt.SetOutputDevice (dev2); + NS_TEST_EXPECT_MSG_EQ (rt.GetOutputDevice (), dev2, "trivial"); + rt.SetInterface (iface2); + NS_TEST_EXPECT_MSG_EQ (rt.GetInterface (), iface2, "trivial"); + rt.SetValidSeqNo (false); + NS_TEST_EXPECT_MSG_EQ (rt.GetValidSeqNo (), false, "trivial"); + rt.SetFlag (INVALID); + NS_TEST_EXPECT_MSG_EQ (rt.GetFlag (), INVALID, "trivial"); + rt.SetFlag (IN_SEARCH); + NS_TEST_EXPECT_MSG_EQ (rt.GetFlag (), IN_SEARCH, "trivial"); + rt.SetHop (12); + NS_TEST_EXPECT_MSG_EQ (rt.GetHop (), 12, "trivial"); + rt.SetLifeTime (Seconds (1)); + NS_TEST_EXPECT_MSG_EQ (rt.GetLifeTime (), Seconds (1), "trivial"); + rt.SetNextHop (Ipv4Address ("1.1.1.1")); + NS_TEST_EXPECT_MSG_EQ (rt.GetNextHop (), Ipv4Address ("1.1.1.1"), "trivial"); + rt.SetUnidirectional (true); + NS_TEST_EXPECT_MSG_EQ (rt.IsUnidirectional (), true, "trivial"); + rt.SetBlacklistTimeout (Seconds (7)); + NS_TEST_EXPECT_MSG_EQ (rt.GetBlacklistTimeout (), Seconds (7), "trivial"); + rt.SetRreqCnt (2); + NS_TEST_EXPECT_MSG_EQ (rt.GetRreqCnt (), 2, "trivial"); + rt.IncrementRreqCnt (); + NS_TEST_EXPECT_MSG_EQ (rt.GetRreqCnt (), 3, "trivial"); + rt.Invalidate (Seconds (13)); + NS_TEST_EXPECT_MSG_EQ (rt.GetFlag (), INVALID, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.GetLifeTime (), Seconds (13), "trivial"); + rt.SetLifeTime (MilliSeconds (100)); + NS_TEST_EXPECT_MSG_EQ (rt.GetLifeTime (), MilliSeconds (100), "trivial"); + Ptr<Ipv4Route> route = rt.GetRoute (); + NS_TEST_EXPECT_MSG_EQ (route->GetDestination (), Ipv4Address ("1.2.3.4"), "trivial"); + + NS_TEST_EXPECT_MSG_EQ (rt.InsertPrecursor (Ipv4Address ("10.0.0.1")), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.IsPrecursorListEmpty (), false, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.InsertPrecursor (Ipv4Address ("10.0.0.2")), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.InsertPrecursor (Ipv4Address ("10.0.0.2")), false, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.LookupPrecursor (Ipv4Address ("10.0.0.3")), false, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.LookupPrecursor (Ipv4Address ("10.0.0.1")), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.DeletePrecursor (Ipv4Address ("10.0.0.2")), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.LookupPrecursor (Ipv4Address ("10.0.0.2")), false, "trivial"); + std::vector<Ipv4Address> prec; + rt.GetPrecursors (prec); + NS_TEST_EXPECT_MSG_EQ (prec.size (), 1, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.InsertPrecursor (Ipv4Address ("10.0.0.4")), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.DeletePrecursor (Ipv4Address ("10.0.0.5")), false, "trivial"); + rt.GetPrecursors (prec); + NS_TEST_EXPECT_MSG_EQ (prec.size (), 2, "trivial"); + rt.DeleteAllPrecursors (); + NS_TEST_EXPECT_MSG_EQ (rt.IsPrecursorListEmpty (), true, "trivial"); + rt.GetPrecursors (prec); + NS_TEST_EXPECT_MSG_EQ (prec.size (), 2, "trivial"); + Simulator::Destroy (); + } +}; + +/** + * \ingroup greyattack-test + * \ingroup tests + * + * \brief Unit test for greyattack routing table + */ +struct greyattackRtableTest : public TestCase +{ + greyattackRtableTest () : TestCase ("Rtable") + { + } + virtual void DoRun () + { + RoutingTable rtable (Seconds (2)); + NS_TEST_EXPECT_MSG_EQ (rtable.GetBadLinkLifetime (), Seconds (2), "trivial"); + rtable.SetBadLinkLifetime (Seconds (1)); + NS_TEST_EXPECT_MSG_EQ (rtable.GetBadLinkLifetime (), Seconds (1), "trivial"); + Ptr<NetDevice> dev; + Ipv4InterfaceAddress iface; + RoutingTableEntry rt (/*output device*/ dev, /*dst*/ Ipv4Address ("1.2.3.4"), /*validSeqNo*/ true, /*seqNo*/ 10, + /*interface*/ iface, /*hop*/ 5, /*next hop*/ Ipv4Address ("1.1.1.1"), /*lifetime*/ Seconds (10)); + NS_TEST_EXPECT_MSG_EQ (rtable.AddRoute (rt), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rtable.AddRoute (rt), false, "trivial"); + RoutingTableEntry rt2 (/*output device*/ dev, /*dst*/ Ipv4Address ("4.3.2.1"), /*validSeqNo*/ false, /*seqNo*/ 0, + /*interface*/ iface, /*hop*/ 15, /*next hop*/ Ipv4Address ("1.1.1.1"), /*lifetime*/ Seconds (1)); + NS_TEST_EXPECT_MSG_EQ (rtable.AddRoute (rt2), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rtable.LookupRoute (rt2.GetDestination (), rt), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt2.GetDestination (), rt.GetDestination (), "trivial"); + rt.SetHop (20); + rt.InsertPrecursor (Ipv4Address ("10.0.0.3")); + NS_TEST_EXPECT_MSG_EQ (rtable.Update (rt), true, "trivial"); + RoutingTableEntry rt3; + NS_TEST_EXPECT_MSG_EQ (rtable.LookupRoute (Ipv4Address ("10.0.0.1"), rt), false, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rtable.Update (rt3), false, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rtable.SetEntryState (Ipv4Address ("10.0.0.1"), INVALID), false, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rtable.SetEntryState (Ipv4Address ("1.2.3.4"), IN_SEARCH), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rtable.DeleteRoute (Ipv4Address ("5.5.5.5")), false, "trivial"); + RoutingTableEntry rt4 (/*output device*/ dev, /*dst*/ Ipv4Address ("5.5.5.5"), /*validSeqNo*/ false, /*seqNo*/ 0, + /*interface*/ iface, /*hop*/ 15, /*next hop*/ Ipv4Address ("1.1.1.1"), /*lifetime*/ Seconds (-10)); + NS_TEST_EXPECT_MSG_EQ (rtable.AddRoute (rt4), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rtable.SetEntryState (Ipv4Address ("5.5.5.5"), INVALID), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rtable.LookupRoute (Ipv4Address ("5.5.5.5"), rt), false, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rtable.MarkLinkAsUnidirectional (Ipv4Address ("1.2.3.4"), Seconds (2)), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rtable.LookupRoute (Ipv4Address ("1.2.3.4"), rt), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.IsUnidirectional (), true, "trivial"); + rt.SetLifeTime (Seconds (-5)); + NS_TEST_EXPECT_MSG_EQ (rtable.Update (rt), true, "trivial"); + std::map<Ipv4Address, uint32_t> unreachable; + rtable.GetListOfDestinationWithNextHop (Ipv4Address ("1.1.1.1"), unreachable); + NS_TEST_EXPECT_MSG_EQ (unreachable.size (), 2, "trivial"); + unreachable.insert (std::make_pair (Ipv4Address ("4.3.2.1"), 3)); + rtable.InvalidateRoutesWithDst (unreachable); + NS_TEST_EXPECT_MSG_EQ (rtable.LookupRoute (Ipv4Address ("4.3.2.1"), rt), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rt.GetFlag (), INVALID, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rtable.DeleteRoute (Ipv4Address ("1.2.3.4")), true, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rtable.DeleteRoute (Ipv4Address ("1.2.3.4")), false, "trivial"); + Simulator::Destroy (); + } +}; + +/** + * \ingroup greyattack-test + * \ingroup tests + * + * \brief greyattack test suite + */ +class greyattackTestSuite : public TestSuite +{ +public: + greyattackTestSuite () : TestSuite ("routing-greyattack", UNIT) + { + AddTestCase (new NeighborTest, TestCase::QUICK); + AddTestCase (new TypeHeaderTest, TestCase::QUICK); + AddTestCase (new RreqHeaderTest, TestCase::QUICK); + AddTestCase (new RrepHeaderTest, TestCase::QUICK); + AddTestCase (new RrepAckHeaderTest, TestCase::QUICK); + AddTestCase (new RerrHeaderTest, TestCase::QUICK); + AddTestCase (new QueueEntryTest, TestCase::QUICK); + AddTestCase (new greyattackRqueueTest, TestCase::QUICK); + AddTestCase (new greyattackRtableEntryTest, TestCase::QUICK); + AddTestCase (new greyattackRtableTest, TestCase::QUICK); + } +} g_greyattackTestSuite; ///< the test suite + +} // namespace greyattack +} // namespace ns3 diff --git a/greyattack-module/test/loopback.cc b/greyattack-module/test/loopback.cc new file mode 100644 index 0000000000000000000000000000000000000000..a22c5ae500f4369c16f5e530b47dc970fb9a6b75 --- /dev/null +++ b/greyattack-module/test/loopback.cc @@ -0,0 +1,197 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Pavel Boyko <boyko@iitp.ru> + */ + +#include "ns3/test.h" +#include "ns3/simulator.h" +#include "ns3/socket-factory.h" +#include "ns3/udp-socket-factory.h" +#include "ns3/mobility-helper.h" +#include "ns3/double.h" +#include "ns3/uinteger.h" +#include "ns3/string.h" +#include "ns3/boolean.h" +#include "ns3/yans-wifi-helper.h" +#include "ns3/internet-stack-helper.h" +#include "ns3/ipv4-address-helper.h" +#include "ns3/abort.h" +#include "ns3/udp-echo-helper.h" +#include "ns3/mobility-model.h" +#include "ns3/pcap-file.h" +#include "ns3/greyattack-helper.h" +#include "ns3/v4ping.h" +#include "ns3/config.h" +#include "ns3/constant-position-mobility-model.h" +#include "ns3/names.h" +#include <sstream> + +namespace ns3 { +namespace greyattack { + +/** + * \ingroup greyattack + * + * \brief greyattack loopback UDP echo test case + */ +class LoopbackTestCase : public TestCase +{ + uint32_t m_count; //!< number of packet received; + Ptr<Socket> m_txSocket; //!< transmit socket; + Ptr<Socket> m_echoSocket; //!< echo socket; + Ptr<Socket> m_rxSocket; //!< receive socket; + uint16_t m_echoSendPort; //!< echo send port; + uint16_t m_echoReplyPort; //!< echo reply port; + + /** + * Send data function + * \param socket The socket to send data + */ + void SendData (Ptr<Socket> socket); + /** + * Receive packet function + * \param socket The socket to receive data + */ + void ReceivePkt (Ptr<Socket> socket); + /** + * Echo data function + * \param socket The socket to echo data + */ + void EchoData (Ptr<Socket> socket); + +public: + LoopbackTestCase (); + void DoRun (); +}; + +LoopbackTestCase::LoopbackTestCase () + : TestCase ("UDP Echo 127.0.0.1 test"), + m_count (0) +{ + m_echoSendPort = 1233; + m_echoReplyPort = 1234; +} + +void LoopbackTestCase::ReceivePkt (Ptr<Socket> socket) +{ + Ptr<Packet> receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max (), 0); + + m_count++; +} + +void +LoopbackTestCase::EchoData (Ptr<Socket> socket) +{ + Address from; + Ptr<Packet> receivedPacket = socket->RecvFrom (std::numeric_limits<uint32_t>::max (), 0, from); + + Ipv4Address src = InetSocketAddress::ConvertFrom (from).GetIpv4 (); + Address to = InetSocketAddress (src, m_echoReplyPort); + + receivedPacket->RemoveAllPacketTags (); + receivedPacket->RemoveAllByteTags (); + + socket->SendTo (receivedPacket, 0, to); +} + +void +LoopbackTestCase::SendData (Ptr<Socket> socket) +{ + Address realTo = InetSocketAddress (Ipv4Address::GetLoopback (), m_echoSendPort); + socket->SendTo (Create<Packet> (123), 0, realTo); + + Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (1.0), + &LoopbackTestCase::SendData, this, socket); +} + +void +LoopbackTestCase::DoRun () +{ + NodeContainer nodes; + nodes.Create (1); + Ptr<MobilityModel> m = CreateObject<ConstantPositionMobilityModel> (); + m->SetPosition (Vector (0, 0, 0)); + nodes.Get (0)->AggregateObject (m); + // Setup WiFi + WifiMacHelper wifiMac; + wifiMac.SetType ("ns3::AdhocWifiMac"); + YansWifiPhyHelper wifiPhy; + YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default (); + wifiPhy.SetChannel (wifiChannel.Create ()); + WifiHelper wifi; + wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue ("OfdmRate6Mbps"), "RtsCtsThreshold", StringValue ("2200")); + NetDeviceContainer devices = wifi.Install (wifiPhy, wifiMac, nodes); + + // Setup TCP/IP & greyattack + greyattackHelper greyattack; // Use default parameters here + InternetStackHelper internetStack; + internetStack.SetRoutingHelper (greyattack); + internetStack.Install (nodes); + Ipv4AddressHelper address; + address.SetBase ("10.1.1.0", "255.255.255.0"); + Ipv4InterfaceContainer interfaces = address.Assign (devices); + + // Setup echos + Ptr<SocketFactory> socketFactory = nodes.Get (0)->GetObject<UdpSocketFactory> (); + m_rxSocket = socketFactory->CreateSocket (); + m_rxSocket->Bind (InetSocketAddress (Ipv4Address::GetLoopback (), m_echoReplyPort)); + m_rxSocket->SetRecvCallback (MakeCallback (&LoopbackTestCase::ReceivePkt, this)); + + m_echoSocket = socketFactory->CreateSocket (); + m_echoSocket->Bind (InetSocketAddress (Ipv4Address::GetLoopback (), m_echoSendPort)); + m_echoSocket->SetRecvCallback (MakeCallback (&LoopbackTestCase::EchoData, this)); + + m_txSocket = socketFactory->CreateSocket (); + + Simulator::ScheduleWithContext (m_txSocket->GetNode ()->GetId (), Seconds (1.0), + &LoopbackTestCase::SendData, this, m_txSocket); + + // Run + Simulator::Stop (Seconds (5)); + Simulator::Run (); + + m_txSocket->Close (); + m_echoSocket->Close (); + m_rxSocket->Close (); + + Simulator::Destroy (); + + // Check that 4 packets delivered + NS_TEST_ASSERT_MSG_EQ (m_count, 4, "Exactly 4 echo replies must be delivered."); +} + +/** + * \ingroup greyattack-test + * \ingroup tests + * + * \brief greyattack Loopback test suite + */ +class greyattackLoopbackTestSuite : public TestSuite +{ +public: + greyattackLoopbackTestSuite () : TestSuite ("routing-greyattack-loopback", SYSTEM) + { + SetDataDir (NS_TEST_SOURCEDIR); + // UDP Echo loopback test case + AddTestCase (new LoopbackTestCase (), TestCase::QUICK); + } +} g_greyattackLoopbackTestSuite; ///< the test suite + + +} // namespace greyattack +} // namespace ns3 diff --git a/greyattack-module/wscript b/greyattack-module/wscript new file mode 100644 index 0000000000000000000000000000000000000000..188523542c07b2a9344ad4a1a2efe009758ebb60 --- /dev/null +++ b/greyattack-module/wscript @@ -0,0 +1,48 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + +def build(bld): + module = bld.create_ns3_module('greydefense-aodv', ['internet', 'wifi']) + module.includes = '.' + module.source = [ + 'model/greydefense-aodv-id-cache.cc', + 'model/greydefense-aodv-dpd.cc', + 'model/greydefense-aodv-rtable.cc', + 'model/greydefense-aodv-rqueue.cc', + 'model/greydefense-aodv-packet.cc', + 'model/greydefense-aodv-neighbor.cc', + 'model/greydefense-aodv-routing-protocol.cc', + 'helper/greydefense-aodv-helper.cc', + ] + + greydefense-aodv_test = bld.create_ns3_module_test_library('greydefense-aodv') + greydefense-aodv_test.source = [ + 'test/greydefense-aodv-id-cache-test-suite.cc', + 'test/greydefense-aodv-test-suite.cc', + 'test/greydefense-aodv-regression.cc', + 'test/bug-772.cc', + 'test/loopback.cc', + ] + + # Tests encapsulating example programs should be listed here + if (bld.env['ENABLE_EXAMPLES']): + greydefense-aodv_test.source.extend([ + # 'test/greydefense-aodv-examples-test-suite.cc', + ]) + + headers = bld(features='ns3header') + headers.module = 'greydefense-aodv' + headers.source = [ + 'model/greydefense-aodv-id-cache.h', + 'model/greydefense-aodv-dpd.h', + 'model/greydefense-aodv-rtable.h', + 'model/greydefense-aodv-rqueue.h', + 'model/greydefense-aodv-packet.h', + 'model/greydefense-aodv-neighbor.h', + 'model/greydefense-aodv-routing-protocol.h', + 'helper/greydefense-aodv-helper.h', + ] + + if bld.env['ENABLE_EXAMPLES']: + bld.recurse('examples') + + bld.ns3_python_bindings() \ No newline at end of file diff --git a/manet-rank-scratch/MainExperiment/debug.py b/manet-rank-scratch/MainExperiment/debug.py new file mode 100644 index 0000000000000000000000000000000000000000..3f428e2379b705abd36847f6e625692fa6690178 --- /dev/null +++ b/manet-rank-scratch/MainExperiment/debug.py @@ -0,0 +1,197 @@ +import re +from collections import defaultdict + +# Define data structures to store parsed information +rejected_nodes_info = [] +forwarded_packets = [] # List of dictionaries to store packet forwarding details +attack_info = [] # List to store attack information + +# Regular expressions for matching log file lines +forward_pattern = re.compile( + r'\+(\d+\.\d+s) \[node (\d+)\] (?:eaer|greydefense)-aodvRoutingProtocol:Forwarding\(\): forwarding packet ID: (\d+) ttl: (\d+) to (\d+\.\d+\.\d+\.\d+) from (\d+\.\d+\.\d+\.\d+) via (\d+\.\d+\.\d+\.\d+)') +send_pattern = re.compile( + r'\+(\d+\.\d+s) \[node (\d+)\] (?:eaer|greydefense)-aodvRoutingProtocol:(?:RouteOutput|SendPacketFromQueue)\(\): sending packet ID: (\d+) ttl: (\d+) to (\d+\.\d+\.\d+\.\d+) from (\d+\.\d+\.\d+\.\d+)(?: via (\d+\.\d+\.\d+\.\d+))?') +attack_pattern = re.compile(r'\+(\d+\.\d+s) \[node (\d+)\] (?:eaer|greyattack)-aodvRoutingProtocol:Forwarding\(\): \[Attack - PACKET_DROP_PERC\]: Dropped packet (\d+) where the next hop was (\d+\.\d+\.\d+\.\d+)') +rejected_node_pattern = re.compile(r'\+(\d+\.\d+s) \[node (\d+)\] (?:eaer|greydefense)-aodvRoutingProtocol:UpdateTrust\(\): \d+ Rejected: (\d+)') +# Dictionary to store the last timestamp for each packet ID +last_timestamps = {} +# list to store the next available new packet ID for retransmissions +new_packet_ids = set() + +# Read the log file and parse lines +with open('network.log', 'r') as log_file: + for line in log_file: + # Check if the line matches the "Forwarding" pattern + forward_match = forward_pattern.match(line) + send_match = send_pattern.match(line) + attack_match = attack_pattern.match(line) + rejected_node_match = rejected_node_pattern.match(line) + + if forward_match: + timestamp, source_node, packet_id, ttl, destination_ip, source_ip, forwarding_node = forward_match.groups() + + elif send_match: + timestamp, source_node, packet_id, ttl, destination_ip, source_ip, forwarding_node = send_match.groups() + + elif attack_match: + timestamp, node_id, packet_id, next_hop = attack_match.groups() + packet_id = int(packet_id) + new_packet_ids.add(packet_id) + + already_counted = False + for attack in attack_info: + if attack['Packet ID'] == packet_id: + already_counted = True + if not already_counted: + attack_info.append({ + 'Timestamp': float(timestamp[:-1]), # Remove 's' and convert to float + 'Node ID': node_id, + 'Packet ID': packet_id, + 'Next Hop': next_hop + }) + else: + packet_id += 10000 + already_counted = False + for attack in attack_info: + if attack['Packet ID'] == packet_id: + already_counted = True + if not already_counted: + attack_info.append({ + 'Timestamp': float(timestamp[:-1]), # Remove 's' and convert to float + 'Node ID': node_id, + 'Packet ID': packet_id, + 'Next Hop': next_hop + }) + else: + print("Something's gone wrong") + continue + + elif rejected_node_match: + timestamp, node_id, rejected_node = rejected_node_match.groups() + rejected_nodes_info.append({ + 'Timestamp': float(timestamp[:-1]), # Remove 's' and convert to float + 'Node ID': node_id, + 'Rejected Node': rejected_node, + }) + continue + + else: + continue + + packet_id = int(packet_id) # Convert packet ID to an integer + + # Remove 's' from the timestamp and convert to float + timestamp = float(timestamp[:-1]) + + last_timestamp = last_timestamps.get(packet_id, 0) + current_timestamp = timestamp + + if current_timestamp - last_timestamp >= 10.0 and packet_id in new_packet_ids: + # This is packet has an ID which is previously been used, add 10000 to the packet ID to keep them unique + packet_id += 10000 + + forwarded_packets.append({ + 'Timestamp': timestamp, + 'Source Node': source_node, + 'Packet ID': packet_id, + 'TTL': ttl, + 'Source IP': source_ip, + 'Destination IP': destination_ip, + 'Forwarding Node': forwarding_node + }) + + # Add the packet_id to the list of IDs + if packet_id not in new_packet_ids: + new_packet_ids.add(packet_id) + else: + forwarded_packets.append({ + 'Timestamp': timestamp, + 'Source Node': source_node, + 'Packet ID': packet_id, + 'TTL': ttl, + 'Source IP': source_ip, + 'Destination IP': destination_ip, + 'Forwarding Node': forwarding_node + }) + + # Add the packet_id to the list of IDs + if packet_id not in new_packet_ids: + new_packet_ids.add(packet_id) + + # Update the last timestamp for the packet ID + last_timestamps[packet_id] = current_timestamp + +# keep track of a few parameters +packets_delivered = 0 +packets_attacked = 0 +packets_total = 0 +last_timestamp = 0.0 + +new_packet_ids = sorted(new_packet_ids) + +for pktid in list(new_packet_ids): + pkts_unique_id = [] + print_route = True + + for pkt in forwarded_packets: + if pkt['Packet ID'] == pktid: + pkts_unique_id.append(pkt) + + pkts_unique_id = sorted(pkts_unique_id, key=lambda x: x['Timestamp']) + rejected_nodes_info = sorted(rejected_nodes_info, key=lambda x: x['Timestamp']) + + # Packets which have not been recorded as forwarded or sent. (This comes from originating node and a route has already been set up) + attack_without_forwarding = False + if not any(pkts_unique_id): + for attack in attack_info: + if attack['Packet ID'] == pktid: + attack_without_forwarding = True + attack_next_hop = attack['Next Hop'] + attack_node = attack['Node ID'] + packets_attacked+=1 + packets_total+=1 + break; + + if attack_without_forwarding: + print('[' + attack_node + '] Packet ID: ' + str(pktid) + ' Attacked, Next Hop: ' + attack_next_hop) + continue + + # we have all forwarding information for the route, now we need to print the route out + route_str = '[ID: ' + str(pktid) + '] Timestamp: ' + str(pkts_unique_id[0]['Timestamp']) + ' ' + pkts_unique_id[0]['Source IP'] + + num_printed_rejected_nodes = 0 + for rejected_node in rejected_nodes_info: + if rejected_node['Timestamp'] < pkts_unique_id[0]['Timestamp']: + print('Node: ' + str(rejected_node['Node ID']) + ' Timestamp: ' + str(rejected_node['Timestamp']) + ' Node Rejected: ' + rejected_node['Rejected Node']) + num_printed_rejected_nodes += 1 + for i in range(num_printed_rejected_nodes): + rejected_nodes_info.pop(0) + + for pkt in pkts_unique_id: + # record the route + route_str += ' -> ' + pkt['Forwarding Node'] + + # check if the packet has reached its destination or not + if pkt['Destination IP'] == pkt['Forwarding Node']: + print_route = False + packets_delivered+=1 + break + + # check if the packet has been intercepted on the route and dropped by the attacker. + for attack in attack_info: + if attack['Packet ID'] == pktid: + print_route = False + packets_attacked+=1 + break + + # total number of packets seen. + packets_total+=1 + + # print the route. + if print_route: + print(route_str) + +print('packets total: ' + str(packets_total)) +print('packets delivered: ' + str((packets_delivered / packets_total))) +print('packets attacked (dropped): ' + str((packets_attacked / packets_total))) +print('packets unaccounted for: ' + str(1 - ((packets_attacked + packets_delivered) / packets_total))) \ No newline at end of file