internet-apps: DHCPv4 application
Special thanks to: - Radu Lupu <rlupu@elcom.pub.ro> - Ankit Deepak <adadeepak8@gmail.com> - Deepti Rajagopal <deeptir96@gmail.com> - Mohit P. Tahiliani <tahiliani.nitk@gmail.com>
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -35,3 +35,5 @@ TAGS
|
||||
|
||||
build-dir/
|
||||
build/
|
||||
/.cproject
|
||||
/.project
|
||||
|
||||
2
AUTHORS
2
AUTHORS
@@ -99,6 +99,7 @@ Björn Lichtblau (lichtbla@informatik.hu-berlin.de)
|
||||
Timo Lindhorst (tlnd@online.de)
|
||||
Erwan Livolant (erwan.livolant@inria.fr)
|
||||
Andrea Lupia (alupia@dimes.unical.it)
|
||||
Radu Lupu <rlupu@elcom.pub.ro>
|
||||
Keith Ma (keith.nwsuaf@gmail.com)
|
||||
Federico Maguolo (maguolof@dei.unipd.it)
|
||||
Antti Makela (zarhan@cc.hut.fi)
|
||||
@@ -144,6 +145,7 @@ Ovidiu Poncea (ovidiu.poncea@cs.pub.ro)
|
||||
Vikas Pushkar (vikaskupushkar@gmail.com)
|
||||
Andrea Ranieri (andreran@uno.it)
|
||||
Bruno Ranieri (Yrrsinn@googlemail.com)
|
||||
Deepti Rajagopal <deeptir96@gmail.com>
|
||||
Varun Reddy (varunamarreddy@gmail.com)
|
||||
Ken Renard (kenneth.renard@arl.army.mil)
|
||||
Manuel Requena (mrequena@cttc.es)
|
||||
|
||||
@@ -14,16 +14,18 @@ The goal of this module is to hold all the Internet-specific applications,
|
||||
and most notably some very specific applications (e.g., ping) or daemons (e.g., radvd). Other non-Internet-specific applications such as packet generators
|
||||
are contained in other modules.
|
||||
|
||||
Model Description
|
||||
*****************
|
||||
|
||||
The source code for the new module lives in the directory ``src/internet-apps``.
|
||||
|
||||
Each application has its own goals, limitations and scope, which are briefly explained
|
||||
in the following.
|
||||
|
||||
All the applications are extensively used in the top-level ``examples``
|
||||
directories. The users are encouraged to check the scripts therein to have a
|
||||
clear overview of the various options and usage tricks.
|
||||
|
||||
|
||||
V4Ping
|
||||
======
|
||||
******
|
||||
|
||||
This app mimics a "ping" (ICMP Echo) using IPv4. The application allows the
|
||||
following attributes to be set:
|
||||
@@ -36,7 +38,7 @@ following attributes to be set:
|
||||
Moreover, the user can access the measured rtt value (as a Traced Source).
|
||||
|
||||
Ping6
|
||||
=====
|
||||
*****
|
||||
|
||||
This app mimics a "ping" (ICMP Echo) using IPv6. The application allows the
|
||||
following attributes to be set:
|
||||
@@ -48,16 +50,77 @@ following attributes to be set:
|
||||
* Max number of packets to send
|
||||
|
||||
Radvd
|
||||
=====
|
||||
*****
|
||||
|
||||
This app mimics a "RADVD" daemon. I.e., the daemon responsible for IPv6 routers
|
||||
advertisements. All the IPv6 routers should have a RADVD daemon installed.
|
||||
|
||||
The configuration of the Radvd application mimics the one of the radvd Linux program.
|
||||
|
||||
Examples and use
|
||||
****************
|
||||
DHCPv4
|
||||
******
|
||||
|
||||
The |ns3| implementation of Dynamic Host Configuration Protocol (DHCP)
|
||||
follows the specifications of :rfc:`2131` and :rfc:`2132`.
|
||||
|
||||
The source code for DHCP is located in ``src/internet-apps/model`` and consists of the
|
||||
following 6 files:
|
||||
|
||||
* dhcp-server.h,
|
||||
* dhcp-server.cc,
|
||||
* dhcp-client.h,
|
||||
* dhcp-client.cc,
|
||||
* dhcp-header.h and
|
||||
* dhcp-header.cc
|
||||
|
||||
Helpers
|
||||
=======
|
||||
|
||||
The following two files have been added to ``src/internet-apps/helper`` for DHCP:
|
||||
|
||||
* dhcp-helper.h and
|
||||
* dhcp-helper.cc
|
||||
|
||||
Tests
|
||||
=====
|
||||
The tests for DHCP can be found at ``src/internet-apps/test/dhcp-test.cc``
|
||||
|
||||
Examples
|
||||
========
|
||||
The examples for DHCP can be found at ``src/internet-apps/examples/dhcp-example.cc``
|
||||
|
||||
|
||||
Scope and Limitations
|
||||
=====================
|
||||
|
||||
The server should be provided with a network address, mask and a range of address
|
||||
for the pool. One client application can be installed on only one netdevice in a
|
||||
node, and can configure address for only that netdevice.
|
||||
|
||||
The following five basic DHCP messages are supported:
|
||||
|
||||
* DHCP DISCOVER
|
||||
* DHCP OFFER
|
||||
* DHCP REQUEST
|
||||
* DHCP ACK
|
||||
* DHCP NACK
|
||||
|
||||
Also, the following eight options of BootP are supported:
|
||||
|
||||
* 1 (Mask)
|
||||
* 50 (Requested Address)
|
||||
* 51 (Address Lease Time)
|
||||
* 53 (DHCP message type)
|
||||
* 54 (DHCP server identifier)
|
||||
* 58 (Address renew time)
|
||||
* 59 (Address rebind time)
|
||||
* 255 (end)
|
||||
|
||||
The client identifier option (61) can be implemented in near future.
|
||||
|
||||
In the current implementation, a DHCP client can obtain IPv4 address dynamically
|
||||
from the DHCP server, and can renew it within a lease time period.
|
||||
|
||||
Multiple DHCP servers can be configured, but the implementation does not support
|
||||
the use of a DHCP Relay yet.
|
||||
|
||||
All the applications are extensively used in the top-level ``examples``
|
||||
directories. The users are encouraged to check the scripts therein to have a
|
||||
clear overview of the various options and usage tricks.
|
||||
|
||||
162
src/internet-apps/examples/dhcp-example.cc
Normal file
162
src/internet-apps/examples/dhcp-example.cc
Normal file
@@ -0,0 +1,162 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 UPB
|
||||
* Copyright (c) 2017 NITK Surathkal
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Author: Radu Lupu <rlupu@elcom.pub.ro>
|
||||
* Ankit Deepak <adadeepak8@gmail.com>
|
||||
* Deepti Rajagopal <deeptir96@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/internet-apps-module.h"
|
||||
#include "ns3/csma-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("DhcpExample");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
CommandLine cmd;
|
||||
|
||||
bool verbose = false;
|
||||
bool tracing = false;
|
||||
cmd.AddValue ("verbose", "turn on the logs", verbose);
|
||||
cmd.AddValue ("tracing", "turn on the tracing", tracing);
|
||||
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
// GlobalValue::Bind ("ChecksumEnabled", BooleanValue (true));
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
LogComponentEnable ("DhcpServer", LOG_LEVEL_ALL);
|
||||
LogComponentEnable ("DhcpClient", LOG_LEVEL_ALL);
|
||||
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
|
||||
LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
|
||||
}
|
||||
|
||||
Time stopTime = Seconds (20);
|
||||
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
NodeContainer nodes;
|
||||
NodeContainer router;
|
||||
nodes.Create (3);
|
||||
router.Create (2);
|
||||
|
||||
NodeContainer net (nodes, router);
|
||||
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
CsmaHelper csma;
|
||||
csma.SetChannelAttribute ("DataRate", StringValue ("5Mbps"));
|
||||
csma.SetChannelAttribute ("Delay", StringValue ("2ms"));
|
||||
csma.SetDeviceAttribute ("Mtu", UintegerValue (1500));
|
||||
NetDeviceContainer devNet = csma.Install (net);
|
||||
|
||||
NodeContainer p2pNodes;
|
||||
p2pNodes.Add (net.Get (4));
|
||||
p2pNodes.Create (1);
|
||||
|
||||
PointToPointHelper pointToPoint;
|
||||
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
|
||||
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
|
||||
|
||||
NetDeviceContainer p2pDevices;
|
||||
p2pDevices = pointToPoint.Install (p2pNodes);
|
||||
|
||||
InternetStackHelper tcpip;
|
||||
tcpip.Install (nodes);
|
||||
tcpip.Install (router);
|
||||
tcpip.Install (p2pNodes.Get (1));
|
||||
|
||||
Ipv4AddressHelper address;
|
||||
address.SetBase ("172.30.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer p2pInterfaces;
|
||||
p2pInterfaces = address.Assign (p2pDevices);
|
||||
|
||||
// manually add a routing entry because we don't want to add a dynamic routing
|
||||
Ipv4StaticRoutingHelper ipv4RoutingHelper;
|
||||
Ptr<Ipv4> ipv4Ptr = p2pNodes.Get (1)->GetObject<Ipv4> ();
|
||||
Ptr<Ipv4StaticRouting> staticRoutingA = ipv4RoutingHelper.GetStaticRouting (ipv4Ptr);
|
||||
staticRoutingA->AddNetworkRouteTo (Ipv4Address ("172.30.0.0"), Ipv4Mask ("/24"),
|
||||
Ipv4Address ("172.30.1.1"), 1);
|
||||
|
||||
NS_LOG_INFO ("Setup the IP addresses and create DHCP applications.");
|
||||
DhcpHelper dhcpHelper;
|
||||
|
||||
// The router must have a fixed IP.
|
||||
Ipv4InterfaceContainer fixedNodes = dhcpHelper.InstallFixedAddress (devNet.Get (4), Ipv4Address ("172.30.0.17"), Ipv4Mask ("/24"));
|
||||
// Not really necessary, IP forwarding is enabled by default in IPv4.
|
||||
fixedNodes.Get (0).first->SetAttribute ("IpForward", BooleanValue (true));
|
||||
|
||||
// DHCP server
|
||||
ApplicationContainer dhcpServerApp = dhcpHelper.InstallDhcpServer (devNet.Get (3), Ipv4Address ("172.30.0.12"),
|
||||
Ipv4Address ("172.30.0.0"), Ipv4Mask ("/24"),
|
||||
Ipv4Address ("172.30.0.10"), Ipv4Address ("172.30.0.15"),
|
||||
Ipv4Address ("172.30.0.17"));
|
||||
|
||||
// This is just to show how it can be done.
|
||||
DynamicCast<DhcpServer> (dhcpServerApp.Get (0))->AddStaticDhcpEntry (devNet.Get (2)->GetAddress (), Ipv4Address ("172.30.0.14"));
|
||||
|
||||
dhcpServerApp.Start (Seconds (0.0));
|
||||
dhcpServerApp.Stop (stopTime);
|
||||
|
||||
// DHCP clients
|
||||
NetDeviceContainer dhcpClientNetDevs;
|
||||
dhcpClientNetDevs.Add (devNet.Get (0));
|
||||
dhcpClientNetDevs.Add (devNet.Get (1));
|
||||
dhcpClientNetDevs.Add (devNet.Get (2));
|
||||
|
||||
ApplicationContainer dhcpClients = dhcpHelper.InstallDhcpClient (dhcpClientNetDevs);
|
||||
dhcpClients.Start (Seconds (1.0));
|
||||
dhcpClients.Stop (stopTime);
|
||||
|
||||
UdpEchoServerHelper echoServer (9);
|
||||
|
||||
ApplicationContainer serverApps = echoServer.Install (p2pNodes.Get (1));
|
||||
serverApps.Start (Seconds (0.0));
|
||||
serverApps.Stop (stopTime);
|
||||
|
||||
UdpEchoClientHelper echoClient (p2pInterfaces.GetAddress (1), 9);
|
||||
echoClient.SetAttribute ("MaxPackets", UintegerValue (100));
|
||||
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
|
||||
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
|
||||
|
||||
ApplicationContainer clientApps = echoClient.Install (nodes.Get (1));
|
||||
clientApps.Start (Seconds (10.0));
|
||||
clientApps.Stop (stopTime);
|
||||
|
||||
Simulator::Stop (stopTime + Seconds (10.0));
|
||||
|
||||
if (tracing)
|
||||
{
|
||||
csma.EnablePcapAll ("dhcp-csma");
|
||||
pointToPoint.EnablePcapAll ("dhcp-p2p");
|
||||
}
|
||||
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
}
|
||||
8
src/internet-apps/examples/wscript
Normal file
8
src/internet-apps/examples/wscript
Normal file
@@ -0,0 +1,8 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
def build(bld):
|
||||
if not bld.env['ENABLE_EXAMPLES']:
|
||||
return;
|
||||
|
||||
obj = bld.create_ns3_program('dhcp-example', ['internet', 'internet-apps', 'csma', 'point-to-point', 'applications'])
|
||||
obj.source = 'dhcp-example.cc'
|
||||
220
src/internet-apps/helper/dhcp-helper.cc
Normal file
220
src/internet-apps/helper/dhcp-helper.cc
Normal file
@@ -0,0 +1,220 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 UPB
|
||||
* Copyright (c) 2017 NITK Surathkal
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Author: Radu Lupu <rlupu@elcom.pub.ro>
|
||||
* Ankit Deepak <adadeepak8@gmail.com>
|
||||
* Deepti Rajagopal <deeptir96@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "dhcp-helper.h"
|
||||
#include "ns3/dhcp-server.h"
|
||||
#include "ns3/dhcp-client.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/names.h"
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/loopback-net-device.h"
|
||||
#include "ns3/traffic-control-layer.h"
|
||||
#include "ns3/traffic-control-helper.h"
|
||||
#include "ns3/log.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("DhcpHelper");
|
||||
|
||||
DhcpHelper::DhcpHelper ()
|
||||
{
|
||||
m_clientFactory.SetTypeId (DhcpClient::GetTypeId ());
|
||||
m_serverFactory.SetTypeId (DhcpServer::GetTypeId ());
|
||||
}
|
||||
|
||||
void DhcpHelper::SetClientAttribute (
|
||||
std::string name,
|
||||
const AttributeValue &value)
|
||||
{
|
||||
m_clientFactory.Set (name, value);
|
||||
}
|
||||
|
||||
void DhcpHelper::SetServerAttribute (
|
||||
std::string name,
|
||||
const AttributeValue &value)
|
||||
{
|
||||
m_serverFactory.Set (name, value);
|
||||
}
|
||||
|
||||
ApplicationContainer DhcpHelper::InstallDhcpClient (Ptr<NetDevice> netDevice) const
|
||||
{
|
||||
return ApplicationContainer (InstallDhcpClientPriv (netDevice));
|
||||
}
|
||||
|
||||
ApplicationContainer DhcpHelper::InstallDhcpClient (NetDeviceContainer netDevices) const
|
||||
{
|
||||
ApplicationContainer apps;
|
||||
for (NetDeviceContainer::Iterator i = netDevices.Begin (); i != netDevices.End (); ++i)
|
||||
{
|
||||
apps.Add (InstallDhcpClientPriv (*i));
|
||||
}
|
||||
return apps;
|
||||
}
|
||||
|
||||
Ptr<Application> DhcpHelper::InstallDhcpClientPriv (Ptr<NetDevice> netDevice) const
|
||||
{
|
||||
Ptr<Node> node = netDevice->GetNode ();
|
||||
NS_ASSERT_MSG (node != 0, "DhcpClientHelper: NetDevice is not not associated with any node -> fail");
|
||||
|
||||
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
|
||||
NS_ASSERT_MSG (ipv4, "DhcpHelper: NetDevice is associated"
|
||||
" with a node without IPv4 stack installed -> fail "
|
||||
"(maybe need to use InternetStackHelper?)");
|
||||
|
||||
int32_t interface = ipv4->GetInterfaceForDevice (netDevice);
|
||||
if (interface == -1)
|
||||
{
|
||||
interface = ipv4->AddInterface (netDevice);
|
||||
}
|
||||
NS_ASSERT_MSG (interface >= 0, "DhcpHelper: Interface index not found");
|
||||
|
||||
ipv4->SetMetric (interface, 1);
|
||||
ipv4->SetUp (interface);
|
||||
|
||||
// Install the default traffic control configuration if the traffic
|
||||
// control layer has been aggregated, if this is not
|
||||
// a loopback interface, and there is no queue disc installed already
|
||||
Ptr<TrafficControlLayer> tc = node->GetObject<TrafficControlLayer> ();
|
||||
if (tc && DynamicCast<LoopbackNetDevice> (netDevice) == 0 && tc->GetRootQueueDiscOnDevice (netDevice) == 0)
|
||||
{
|
||||
NS_LOG_LOGIC ("DhcpHelper - Installing default traffic control configuration");
|
||||
TrafficControlHelper tcHelper = TrafficControlHelper::Default ();
|
||||
tcHelper.Install (netDevice);
|
||||
}
|
||||
|
||||
Ptr<DhcpClient> app = DynamicCast <DhcpClient> (m_clientFactory.Create<DhcpClient> ());
|
||||
app->SetDhcpClientNetDevice (netDevice);
|
||||
node->AddApplication (app);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
ApplicationContainer DhcpHelper::InstallDhcpServer (Ptr<NetDevice> netDevice, Ipv4Address serverAddr,
|
||||
Ipv4Address poolAddr, Ipv4Mask poolMask,
|
||||
Ipv4Address minAddr, Ipv4Address maxAddr,
|
||||
Ipv4Address gateway)
|
||||
{
|
||||
m_serverFactory.Set ("PoolAddresses", Ipv4AddressValue (poolAddr));
|
||||
m_serverFactory.Set ("PoolMask", Ipv4MaskValue (poolMask));
|
||||
m_serverFactory.Set ("FirstAddress", Ipv4AddressValue (minAddr));
|
||||
m_serverFactory.Set ("LastAddress", Ipv4AddressValue (maxAddr));
|
||||
m_serverFactory.Set ("Gateway", Ipv4AddressValue (gateway));
|
||||
|
||||
Ptr<Node> node = netDevice->GetNode ();
|
||||
NS_ASSERT_MSG (node != 0, "DhcpHelper: NetDevice is not not associated with any node -> fail");
|
||||
|
||||
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
|
||||
NS_ASSERT_MSG (ipv4, "DhcpHelper: NetDevice is associated"
|
||||
" with a node without IPv4 stack installed -> fail "
|
||||
"(maybe need to use InternetStackHelper?)");
|
||||
|
||||
int32_t interface = ipv4->GetInterfaceForDevice (netDevice);
|
||||
if (interface == -1)
|
||||
{
|
||||
interface = ipv4->AddInterface (netDevice);
|
||||
}
|
||||
NS_ASSERT_MSG (interface >= 0, "DhcpHelper: Interface index not found");
|
||||
|
||||
Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (serverAddr, poolMask);
|
||||
ipv4->AddAddress (interface, ipv4Addr);
|
||||
ipv4->SetMetric (interface, 1);
|
||||
ipv4->SetUp (interface);
|
||||
|
||||
// Install the default traffic control configuration if the traffic
|
||||
// control layer has been aggregated, if this is not
|
||||
// a loopback interface, and there is no queue disc installed already
|
||||
Ptr<TrafficControlLayer> tc = node->GetObject<TrafficControlLayer> ();
|
||||
if (tc && DynamicCast<LoopbackNetDevice> (netDevice) == 0 && tc->GetRootQueueDiscOnDevice (netDevice) == 0)
|
||||
{
|
||||
NS_LOG_LOGIC ("DhcpHelper - Installing default traffic control configuration");
|
||||
TrafficControlHelper tcHelper = TrafficControlHelper::Default ();
|
||||
tcHelper.Install (netDevice);
|
||||
}
|
||||
|
||||
// check that the already fixed addresses are not in conflict with the pool
|
||||
std::list<Ipv4Address>::iterator iter;
|
||||
for (iter=m_fixedAddresses.begin (); iter!=m_fixedAddresses.end (); iter ++)
|
||||
{
|
||||
if (iter->Get () >= minAddr.Get () && iter->Get () <= maxAddr.Get ())
|
||||
{
|
||||
NS_ABORT_MSG ("DhcpHelper: Fixed address can not conflict with a pool: " << *iter << " is in [" << minAddr << ", " << maxAddr << "]");
|
||||
}
|
||||
}
|
||||
m_addressPools.push_back (std::make_pair (minAddr, maxAddr));
|
||||
|
||||
Ptr<Application> app = m_serverFactory.Create<DhcpServer> ();
|
||||
node->AddApplication (app);
|
||||
return ApplicationContainer (app);
|
||||
}
|
||||
|
||||
Ipv4InterfaceContainer DhcpHelper::InstallFixedAddress (Ptr<NetDevice> netDevice, Ipv4Address addr, Ipv4Mask mask)
|
||||
{
|
||||
Ipv4InterfaceContainer retval;
|
||||
|
||||
Ptr<Node> node = netDevice->GetNode ();
|
||||
NS_ASSERT_MSG (node != 0, "DhcpHelper: NetDevice is not not associated with any node -> fail");
|
||||
|
||||
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
|
||||
NS_ASSERT_MSG (ipv4, "DhcpHelper: NetDevice is associated"
|
||||
" with a node without IPv4 stack installed -> fail "
|
||||
"(maybe need to use InternetStackHelper?)");
|
||||
|
||||
int32_t interface = ipv4->GetInterfaceForDevice (netDevice);
|
||||
if (interface == -1)
|
||||
{
|
||||
interface = ipv4->AddInterface (netDevice);
|
||||
}
|
||||
NS_ASSERT_MSG (interface >= 0, "DhcpHelper: Interface index not found");
|
||||
|
||||
Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (addr, mask);
|
||||
ipv4->AddAddress (interface, ipv4Addr);
|
||||
ipv4->SetMetric (interface, 1);
|
||||
ipv4->SetUp (interface);
|
||||
retval.Add (ipv4, interface);
|
||||
|
||||
// Install the default traffic control configuration if the traffic
|
||||
// control layer has been aggregated, if this is not
|
||||
// a loopback interface, and there is no queue disc installed already
|
||||
Ptr<TrafficControlLayer> tc = node->GetObject<TrafficControlLayer> ();
|
||||
if (tc && DynamicCast<LoopbackNetDevice> (netDevice) == 0 && tc->GetRootQueueDiscOnDevice (netDevice) == 0)
|
||||
{
|
||||
NS_LOG_LOGIC ("DhcpHelper - Installing default traffic control configuration");
|
||||
TrafficControlHelper tcHelper = TrafficControlHelper::Default ();
|
||||
tcHelper.Install (netDevice);
|
||||
}
|
||||
|
||||
// check that the already fixed addresses are not in conflict with the pool
|
||||
std::list<std::pair<Ipv4Address, Ipv4Address> >::iterator iter;
|
||||
for (iter=m_addressPools.begin (); iter!=m_addressPools.end (); iter ++)
|
||||
{
|
||||
if (addr.Get () >= iter->first.Get () && addr.Get () <= iter->second.Get ())
|
||||
{
|
||||
NS_ABORT_MSG ("DhcpHelper: Fixed address can not conflict with a pool: " << addr << " is in [" << iter->first << ", " << iter->second << "]");
|
||||
}
|
||||
}
|
||||
m_fixedAddresses.push_back (addr);
|
||||
return retval;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
118
src/internet-apps/helper/dhcp-helper.h
Normal file
118
src/internet-apps/helper/dhcp-helper.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 UPB
|
||||
* Copyright (c) 2017 NITK Surathkal
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Author: Radu Lupu <rlupu@elcom.pub.ro>
|
||||
* Ankit Deepak <adadeepak8@gmail.com>
|
||||
* Deepti Rajagopal <deeptir96@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DHCP_HELPER_H
|
||||
#define DHCP_HELPER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "ns3/application-container.h"
|
||||
#include "ns3/net-device-container.h"
|
||||
#include "ns3/object-factory.h"
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/ipv4-interface-container.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \ingroup dhcp
|
||||
*
|
||||
* \class DhcpHelper
|
||||
* \brief The helper class used to configure and install DHCP applications on nodes
|
||||
*/
|
||||
class DhcpHelper
|
||||
{
|
||||
public:
|
||||
DhcpHelper ();
|
||||
|
||||
/**
|
||||
* \brief Set DHCP client attributes
|
||||
* \param name Name of the attribute
|
||||
* \param value Value to be set
|
||||
*/
|
||||
void SetClientAttribute (std::string name, const AttributeValue &value);
|
||||
|
||||
/**
|
||||
* \brief Set DHCP server attributes
|
||||
* \param name Name of the attribute
|
||||
* \param value Value to be set
|
||||
*/
|
||||
void SetServerAttribute (std::string name, const AttributeValue &value);
|
||||
|
||||
/**
|
||||
* \brief Install DHCP client of a nodes / NetDevice
|
||||
* \param netDevice The NetDevice on which DHCP client application has to be installed
|
||||
* \return The application container with DHCP client installed
|
||||
*/
|
||||
ApplicationContainer InstallDhcpClient (Ptr<NetDevice> netDevice) const;
|
||||
|
||||
/**
|
||||
* \brief Install DHCP client of a set of nodes / NetDevices
|
||||
* \param netDevices The NetDevices on which DHCP client application has to be installed
|
||||
* \return The application container with DHCP client installed
|
||||
*/
|
||||
ApplicationContainer InstallDhcpClient (NetDeviceContainer netDevices) const;
|
||||
|
||||
/**
|
||||
* \brief Install DHCP server of a node / NetDevice
|
||||
*
|
||||
* Note: the server address must be coherent with the pool address, because
|
||||
* DHCP relays are not yet supported.
|
||||
*
|
||||
* \param netDevice The NetDevice on which DHCP server application has to be installed
|
||||
* \param serverAddr The Ipv4Address of the server
|
||||
* \param poolAddr The Ipv4Address (network part) of the allocated pool
|
||||
* \param poolMask The mask of the allocated pool
|
||||
* \param minAddr The lower bound of the Ipv4Address pool
|
||||
* \param maxAddr The upper bound of the Ipv4Address pool
|
||||
* \param gateway The Ipv4Address of default gateway (optional)
|
||||
* \return The application container with DHCP server installed
|
||||
*/
|
||||
ApplicationContainer InstallDhcpServer (Ptr<NetDevice> netDevice, Ipv4Address serverAddr,
|
||||
Ipv4Address poolAddr, Ipv4Mask poolMask,
|
||||
Ipv4Address minAddr, Ipv4Address maxAddr,
|
||||
Ipv4Address gateway = Ipv4Address ());
|
||||
/**
|
||||
* \brief Assign a fixed IP addresses to a net device.
|
||||
* \param netDevice The NetDevice on which the address has to be installed
|
||||
* \param serverAddr The Ipv4Address
|
||||
* \param poolMask The network mask
|
||||
*/
|
||||
Ipv4InterfaceContainer InstallFixedAddress (Ptr<NetDevice> netDevice, Ipv4Address addr, Ipv4Mask mask);
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Function to install DHCP client on a node
|
||||
* \param node The node on which DHCP client application has to be installed
|
||||
* \return The pointer to the installed DHCP client
|
||||
*/
|
||||
Ptr<Application> InstallDhcpClientPriv (Ptr<NetDevice> netDevice) const;
|
||||
ObjectFactory m_clientFactory; //!< DHCP client factory
|
||||
ObjectFactory m_serverFactory; //!< DHCP server factory
|
||||
std::list<Ipv4Address> m_fixedAddresses; //!< list of fixed addresses already allocated.
|
||||
std::list< std::pair <Ipv4Address, Ipv4Address> > m_addressPools; //!< list of address pools.
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* DHCP_HELPER_H */
|
||||
506
src/internet-apps/model/dhcp-client.cc
Normal file
506
src/internet-apps/model/dhcp-client.cc
Normal file
@@ -0,0 +1,506 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 UPB
|
||||
* Copyright (c) 2017 NITK Surathkal
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Author: Radu Lupu <rlupu@elcom.pub.ro>
|
||||
* Ankit Deepak <adadeepak8@gmail.com>
|
||||
* Deepti Rajagopal <deeptir96@gmail.com>
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <list>
|
||||
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/double.h"
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/socket-factory.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/ipv4-static-routing-helper.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/random-variable-stream.h"
|
||||
#include "ns3/pointer.h"
|
||||
#include "ns3/string.h"
|
||||
#include "ns3/ipv4-routing-table-entry.h"
|
||||
#include "dhcp-client.h"
|
||||
#include "dhcp-header.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("DhcpClient");
|
||||
NS_OBJECT_ENSURE_REGISTERED (DhcpClient);
|
||||
|
||||
TypeId
|
||||
DhcpClient::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::DhcpClient")
|
||||
.SetParent<Application> ()
|
||||
.AddConstructor<DhcpClient> ()
|
||||
.SetGroupName ("Internet-Apps")
|
||||
.AddAttribute ("RTRS", "Time for retransmission of Discover message",
|
||||
TimeValue (Seconds (5)),
|
||||
MakeTimeAccessor (&DhcpClient::m_rtrs),
|
||||
MakeTimeChecker ())
|
||||
.AddAttribute ("Collect", "Time for which offer collection starts",
|
||||
TimeValue (Seconds (5)),
|
||||
MakeTimeAccessor (&DhcpClient::m_collect),
|
||||
MakeTimeChecker ())
|
||||
.AddAttribute ("ReRequest", "Time after which request will be resent to next server",
|
||||
TimeValue (Seconds (10)),
|
||||
MakeTimeAccessor (&DhcpClient::m_nextoffer),
|
||||
MakeTimeChecker ())
|
||||
.AddAttribute ("Transactions",
|
||||
"The possible value of transaction numbers ",
|
||||
StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=1000000.0]"),
|
||||
MakePointerAccessor (&DhcpClient::m_ran),
|
||||
MakePointerChecker<RandomVariableStream> ())
|
||||
.AddTraceSource ("NewLease",
|
||||
"Get a NewLease",
|
||||
MakeTraceSourceAccessor (&DhcpClient::m_newLease),
|
||||
"ns3::Ipv4Address::TracedCallback")
|
||||
.AddTraceSource ("ExpireLease",
|
||||
"A lease expires",
|
||||
MakeTraceSourceAccessor (&DhcpClient::m_expiry),
|
||||
"ns3::Ipv4Address::TracedCallback");
|
||||
return tid;
|
||||
}
|
||||
|
||||
DhcpClient::DhcpClient ()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
m_server = Ipv4Address::GetAny ();
|
||||
m_socket = 0;
|
||||
m_refreshEvent = EventId ();
|
||||
m_requestEvent = EventId ();
|
||||
m_discoverEvent = EventId ();
|
||||
m_rebindEvent = EventId ();
|
||||
m_nextOfferEvent = EventId ();
|
||||
m_timeout = EventId ();
|
||||
}
|
||||
|
||||
DhcpClient::DhcpClient (Ptr<NetDevice> netDevice)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
m_device = netDevice;
|
||||
m_server = Ipv4Address::GetAny ();
|
||||
m_socket = 0;
|
||||
m_refreshEvent = EventId ();
|
||||
m_requestEvent = EventId ();
|
||||
m_discoverEvent = EventId ();
|
||||
m_rebindEvent = EventId ();
|
||||
m_nextOfferEvent = EventId ();
|
||||
m_timeout = EventId ();
|
||||
}
|
||||
|
||||
DhcpClient::~DhcpClient ()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
}
|
||||
|
||||
Ptr<NetDevice> DhcpClient::GetDhcpClientNetDevice (void)
|
||||
{
|
||||
return m_device;
|
||||
}
|
||||
|
||||
|
||||
void DhcpClient::SetDhcpClientNetDevice (Ptr<NetDevice> netDevice)
|
||||
{
|
||||
m_device = netDevice;
|
||||
}
|
||||
|
||||
Ipv4Address DhcpClient::GetDhcpServer (void)
|
||||
{
|
||||
return m_server;
|
||||
}
|
||||
|
||||
void
|
||||
DhcpClient::DoDispose (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
m_device = 0;
|
||||
|
||||
Application::DoDispose ();
|
||||
}
|
||||
|
||||
int64_t
|
||||
DhcpClient::AssignStreams (int64_t stream)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << stream);
|
||||
m_ran->SetStream (stream);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
DhcpClient::StartApplication (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
m_remoteAddress = Ipv4Address ("255.255.255.255");
|
||||
m_myAddress = Ipv4Address ("0.0.0.0");
|
||||
m_gateway = Ipv4Address ("0.0.0.0");
|
||||
Ptr<Ipv4> ipv4 = GetNode ()->GetObject<Ipv4> ();
|
||||
uint32_t ifIndex = ipv4->GetInterfaceForDevice (m_device);
|
||||
|
||||
// We need to cleanup the type from the stored chaddr, or later we'll fail to compare it.
|
||||
// Moreover, the length is always 16, because chaddr is 16 bytes.
|
||||
Address myAddress = m_device->GetAddress ();
|
||||
NS_LOG_INFO ("My address is " << myAddress);
|
||||
uint8_t addr[Address::MAX_SIZE];
|
||||
std::memset (addr, 0, Address::MAX_SIZE);
|
||||
uint32_t len = myAddress.CopyTo (addr);
|
||||
NS_ASSERT_MSG (len <= 16, "DHCP client can not handle a chaddr larger than 16 bytes");
|
||||
m_chaddr.CopyFrom (addr, 16);
|
||||
NS_LOG_INFO ("My m_chaddr is " << m_chaddr);
|
||||
|
||||
bool found = false;
|
||||
for (uint32_t i = 0; i < ipv4->GetNAddresses (ifIndex); i++)
|
||||
{
|
||||
if (ipv4->GetAddress (ifIndex, i).GetLocal () == m_myAddress)
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
ipv4->AddAddress (ifIndex, Ipv4InterfaceAddress (Ipv4Address ("0.0.0.0"),Ipv4Mask ("/0")));
|
||||
}
|
||||
if (m_socket == 0)
|
||||
{
|
||||
TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
|
||||
m_socket = Socket::CreateSocket (GetNode (), tid);
|
||||
InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), 68);
|
||||
m_socket->SetAllowBroadcast (true);
|
||||
m_socket->Bind (local);
|
||||
m_socket->BindToNetDevice (m_device);
|
||||
}
|
||||
m_socket->SetRecvCallback (MakeCallback (&DhcpClient::NetHandler, this));
|
||||
|
||||
m_device->AddLinkChangeCallback (MakeCallback (&DhcpClient::LinkStateHandler, this));
|
||||
Boot ();
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
DhcpClient::StopApplication ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
Simulator::Remove (m_discoverEvent);
|
||||
Simulator::Remove (m_requestEvent);
|
||||
Simulator::Remove (m_rebindEvent);
|
||||
Simulator::Remove (m_refreshEvent);
|
||||
Simulator::Remove (m_timeout);
|
||||
Simulator::Remove (m_nextOfferEvent);
|
||||
Ptr<Ipv4> ipv4 = GetNode ()->GetObject<Ipv4> ();
|
||||
|
||||
int32_t ifIndex = ipv4->GetInterfaceForDevice (m_device);
|
||||
for (uint32_t i = 0; i < ipv4->GetNAddresses (ifIndex); i++)
|
||||
{
|
||||
if (ipv4->GetAddress (ifIndex,i).GetLocal () == m_myAddress)
|
||||
{
|
||||
ipv4->RemoveAddress (ifIndex, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
|
||||
m_socket->Close ();
|
||||
}
|
||||
|
||||
void DhcpClient::LinkStateHandler (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
if (m_device->IsLinkUp ())
|
||||
{
|
||||
NS_LOG_INFO ("Link up at " << Simulator::Now ().As (Time::S));
|
||||
m_socket->SetRecvCallback (MakeCallback (&DhcpClient::NetHandler, this));
|
||||
StartApplication ();
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_INFO ("Link down at " << Simulator::Now ().As (Time::S)); //reinitialization
|
||||
Simulator::Remove (m_refreshEvent); //stop refresh timer!!!!
|
||||
Simulator::Remove (m_rebindEvent);
|
||||
Simulator::Remove (m_timeout);
|
||||
m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ()); //stop receiving on this socket !!!
|
||||
|
||||
Ptr<Ipv4> ipv4MN = GetNode ()->GetObject<Ipv4> ();
|
||||
int32_t ifIndex = ipv4MN->GetInterfaceForDevice (m_device);
|
||||
|
||||
for (uint32_t i = 0; i < ipv4MN->GetNAddresses (ifIndex); i++)
|
||||
{
|
||||
if (ipv4MN->GetAddress (ifIndex,i).GetLocal () == m_myAddress)
|
||||
{
|
||||
ipv4MN->RemoveAddress (ifIndex, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ipv4StaticRoutingHelper ipv4RoutingHelper;
|
||||
Ptr<Ipv4StaticRouting> staticRouting = ipv4RoutingHelper.GetStaticRouting (ipv4MN);
|
||||
uint32_t i;
|
||||
for (i = 0; i < staticRouting->GetNRoutes (); i++)
|
||||
{
|
||||
if (staticRouting->GetRoute (i).GetGateway () == m_gateway)
|
||||
{
|
||||
staticRouting->RemoveRoute (i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DhcpClient::NetHandler (Ptr<Socket> socket)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << socket);
|
||||
|
||||
Address from;
|
||||
Ptr<Packet> packet = m_socket->RecvFrom (from);
|
||||
DhcpHeader header;
|
||||
if (packet->RemoveHeader (header) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (header.GetChaddr () != m_chaddr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (m_state == WAIT_OFFER && header.GetType () == DhcpHeader::DHCPOFFER)
|
||||
{
|
||||
OfferHandler (header);
|
||||
}
|
||||
if (m_state == WAIT_ACK && header.GetType () == DhcpHeader::DHCPACK)
|
||||
{
|
||||
Simulator::Remove (m_nextOfferEvent);
|
||||
AcceptAck (header,from);
|
||||
}
|
||||
if (m_state == WAIT_ACK && header.GetType () == DhcpHeader::DHCPNACK)
|
||||
{
|
||||
Simulator::Remove (m_nextOfferEvent);
|
||||
Boot ();
|
||||
}
|
||||
}
|
||||
|
||||
void DhcpClient::Boot (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
DhcpHeader header;
|
||||
Ptr<Packet> packet;
|
||||
packet = Create<Packet> ();
|
||||
header.ResetOpt ();
|
||||
m_tran = (uint32_t) (m_ran->GetValue ());
|
||||
header.SetTran (m_tran);
|
||||
header.SetType (DhcpHeader::DHCPDISCOVER);
|
||||
header.SetTime ();
|
||||
header.SetChaddr (m_chaddr);
|
||||
packet->AddHeader (header);
|
||||
|
||||
if ((m_socket->SendTo (packet, 0, InetSocketAddress (Ipv4Address ("255.255.255.255"), DHCP_PEER_PORT))) >= 0)
|
||||
{
|
||||
NS_LOG_INFO ("DHCP DISCOVER sent" );
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_INFO ("Error while sending DHCP DISCOVER to " << m_remoteAddress);
|
||||
}
|
||||
m_state = WAIT_OFFER;
|
||||
m_offered = false;
|
||||
m_discoverEvent = Simulator::Schedule (m_rtrs, &DhcpClient::Boot, this);
|
||||
}
|
||||
|
||||
void DhcpClient::OfferHandler (DhcpHeader header)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << header);
|
||||
|
||||
m_offerList.push_back (header);
|
||||
if (m_offered == false)
|
||||
{
|
||||
Simulator::Remove (m_discoverEvent);
|
||||
m_offered = true;
|
||||
Simulator::Schedule (m_collect, &DhcpClient::Select, this);
|
||||
}
|
||||
}
|
||||
|
||||
void DhcpClient::Select (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
if (m_offerList.empty ())
|
||||
{
|
||||
Boot ();
|
||||
return;
|
||||
}
|
||||
|
||||
DhcpHeader header = m_offerList.front ();
|
||||
m_offerList.pop_front ();
|
||||
m_lease = Time (Seconds (header.GetLease ()));
|
||||
m_renew = Time (Seconds (header.GetRenew ()));
|
||||
m_rebind = Time (Seconds (header.GetRebind ()));
|
||||
m_offeredAddress = header.GetYiaddr ();
|
||||
m_myMask = Ipv4Mask (header.GetMask ());
|
||||
m_server = header.GetDhcps ();
|
||||
m_gateway = header.GetRouter ();
|
||||
m_offerList.clear ();
|
||||
m_offered = false;
|
||||
Request ();
|
||||
}
|
||||
|
||||
void DhcpClient::Request (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
DhcpHeader header;
|
||||
Ptr<Packet> packet;
|
||||
if (m_state != REFRESH_LEASE)
|
||||
{
|
||||
packet = Create<Packet> ();
|
||||
header.ResetOpt ();
|
||||
header.SetType (DhcpHeader::DHCPREQ);
|
||||
header.SetTime ();
|
||||
header.SetTran (m_tran);
|
||||
header.SetReq (m_offeredAddress);
|
||||
header.SetChaddr (m_chaddr);
|
||||
packet->AddHeader (header);
|
||||
m_socket->SendTo (packet, 0, InetSocketAddress (Ipv4Address ("255.255.255.255"), DHCP_PEER_PORT));
|
||||
m_state = WAIT_ACK;
|
||||
m_nextOfferEvent = Simulator::Schedule (m_nextoffer, &DhcpClient::Select, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t addr = m_myAddress.Get ();
|
||||
packet = Create<Packet> ((uint8_t*)&addr, sizeof(addr));
|
||||
header.ResetOpt ();
|
||||
m_tran = (uint32_t) (m_ran->GetValue ());
|
||||
header.SetTran (m_tran);
|
||||
header.SetTime ();
|
||||
header.SetType (DhcpHeader::DHCPREQ);
|
||||
header.SetReq (m_myAddress);
|
||||
m_offeredAddress = m_myAddress;
|
||||
header.SetChaddr (m_chaddr);
|
||||
packet->AddHeader (header);
|
||||
if ((m_socket->SendTo (packet, 0, InetSocketAddress (m_remoteAddress, DHCP_PEER_PORT))) >= 0)
|
||||
{
|
||||
NS_LOG_INFO ("DHCP REQUEST sent");
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_INFO ("Error while sending DHCP REQ to " << m_remoteAddress);
|
||||
}
|
||||
m_state = WAIT_ACK;
|
||||
}
|
||||
}
|
||||
|
||||
void DhcpClient::AcceptAck (DhcpHeader header, Address from)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << header << from);
|
||||
|
||||
Simulator::Remove (m_rebindEvent);
|
||||
Simulator::Remove (m_refreshEvent);
|
||||
Simulator::Remove (m_timeout);
|
||||
NS_LOG_INFO ("DHCP ACK received");
|
||||
Ptr<Ipv4> ipv4 = GetNode ()->GetObject<Ipv4> ();
|
||||
int32_t ifIndex = ipv4->GetInterfaceForDevice (m_device);
|
||||
|
||||
for (uint32_t i = 0; i < ipv4->GetNAddresses (ifIndex); i++)
|
||||
{
|
||||
if (ipv4->GetAddress (ifIndex,i).GetLocal () == m_myAddress)
|
||||
{
|
||||
NS_LOG_LOGIC ("Got a new address, removing old one: " << m_myAddress);
|
||||
ipv4->RemoveAddress (ifIndex, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ipv4->AddAddress (ifIndex, Ipv4InterfaceAddress (m_offeredAddress, m_myMask));
|
||||
ipv4->SetUp (ifIndex);
|
||||
|
||||
InetSocketAddress remote = InetSocketAddress (InetSocketAddress::ConvertFrom (from).GetIpv4 (), DHCP_PEER_PORT);
|
||||
m_socket->Connect (remote);
|
||||
if (m_myAddress != m_offeredAddress)
|
||||
{
|
||||
m_newLease (m_offeredAddress);
|
||||
if (m_myAddress != Ipv4Address ("0.0.0.0"))
|
||||
{
|
||||
m_expiry (m_myAddress);
|
||||
}
|
||||
}
|
||||
m_myAddress = m_offeredAddress;
|
||||
Ipv4StaticRoutingHelper ipv4RoutingHelper;
|
||||
Ptr<Ipv4StaticRouting> staticRouting = ipv4RoutingHelper.GetStaticRouting (ipv4);
|
||||
if (m_gateway == Ipv4Address ("0.0.0.0"))
|
||||
{
|
||||
m_gateway = InetSocketAddress::ConvertFrom (from).GetIpv4 ();
|
||||
}
|
||||
|
||||
staticRouting->SetDefaultRoute (m_gateway, ifIndex, 0);
|
||||
|
||||
m_remoteAddress = InetSocketAddress::ConvertFrom (from).GetIpv4 ();
|
||||
NS_LOG_INFO ("Current DHCP Server is " << m_remoteAddress);
|
||||
|
||||
m_offerList.clear ();
|
||||
m_refreshEvent = Simulator::Schedule (m_renew, &DhcpClient::Request, this);
|
||||
m_rebindEvent = Simulator::Schedule (m_rebind, &DhcpClient::Request, this);
|
||||
m_timeout = Simulator::Schedule (m_lease, &DhcpClient::RemoveAndStart, this);
|
||||
m_state = REFRESH_LEASE;
|
||||
}
|
||||
|
||||
void DhcpClient::RemoveAndStart ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
Simulator::Remove (m_nextOfferEvent);
|
||||
Simulator::Remove (m_refreshEvent);
|
||||
Simulator::Remove (m_rebindEvent);
|
||||
Simulator::Remove (m_timeout);
|
||||
|
||||
Ptr<Ipv4> ipv4MN = GetNode ()->GetObject<Ipv4> ();
|
||||
int32_t ifIndex = ipv4MN->GetInterfaceForDevice (m_device);
|
||||
|
||||
for (uint32_t i = 0; i < ipv4MN->GetNAddresses (ifIndex); i++)
|
||||
{
|
||||
if (ipv4MN->GetAddress (ifIndex,i).GetLocal () == m_myAddress)
|
||||
{
|
||||
ipv4MN->RemoveAddress (ifIndex, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_expiry (m_myAddress);
|
||||
Ipv4StaticRoutingHelper ipv4RoutingHelper;
|
||||
Ptr<Ipv4StaticRouting> staticRouting = ipv4RoutingHelper.GetStaticRouting (ipv4MN);
|
||||
uint32_t i;
|
||||
for (i = 0; i < staticRouting->GetNRoutes (); i++)
|
||||
{
|
||||
if (staticRouting->GetRoute (i).GetGateway () == m_gateway)
|
||||
{
|
||||
staticRouting->RemoveRoute (i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
StartApplication ();
|
||||
}
|
||||
|
||||
} // Namespace ns3
|
||||
195
src/internet-apps/model/dhcp-client.h
Normal file
195
src/internet-apps/model/dhcp-client.h
Normal file
@@ -0,0 +1,195 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 UPB
|
||||
* Copyright (c) 2017 NITK Surathkal
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Author: Radu Lupu <rlupu@elcom.pub.ro>
|
||||
* Ankit Deepak <adadeepak8@gmail.com>
|
||||
* Deepti Rajagopal <deeptir96@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DHCP_CLIENT_H
|
||||
#define DHCP_CLIENT_H
|
||||
|
||||
#include "ns3/application.h"
|
||||
#include "ns3/event-id.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/random-variable-stream.h"
|
||||
#include "ns3/traced-value.h"
|
||||
#include "dhcp-header.h"
|
||||
#include <list>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class Socket;
|
||||
class Packet;
|
||||
|
||||
/**
|
||||
* \ingroup dhcp
|
||||
*
|
||||
* \class DhcpClient
|
||||
* \brief Implements the functionality of a DHCP client
|
||||
*/
|
||||
class DhcpClient : public Application
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId
|
||||
GetTypeId (void);
|
||||
|
||||
DhcpClient ();
|
||||
virtual ~DhcpClient ();
|
||||
|
||||
/**
|
||||
* \brief Constructor
|
||||
* \param netDevice the NetDevice DHCP should work on
|
||||
*/
|
||||
DhcpClient (Ptr<NetDevice> netDevice);
|
||||
|
||||
/**
|
||||
* \brief Get the the NetDevice DHCP should work on
|
||||
* \return the NetDevice DHCP should work on
|
||||
*/
|
||||
Ptr<NetDevice> GetDhcpClientNetDevice (void);
|
||||
|
||||
/**
|
||||
* \brief Set the NetDevice DHCP should work on
|
||||
* \param netDevice the NetDevice DHCP should work on
|
||||
*/
|
||||
void SetDhcpClientNetDevice (Ptr<NetDevice> netDevice);
|
||||
|
||||
/**
|
||||
* \brief Get the IPv4Address of current DHCP server
|
||||
* \return Ipv4Address of current DHCP server
|
||||
*/
|
||||
Ipv4Address GetDhcpServer (void);
|
||||
|
||||
/**
|
||||
* 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 DoDispose (void);
|
||||
|
||||
private:
|
||||
enum States
|
||||
{
|
||||
WAIT_OFFER = 1, //!< State of a client that waits for the offer
|
||||
REFRESH_LEASE = 2, //!< State of a client that needs to refresh the lease
|
||||
WAIT_ACK = 9 //!< State of a client that waits for acknowledgment
|
||||
};
|
||||
|
||||
static const int DHCP_PEER_PORT = 67; //!< DHCP server port
|
||||
|
||||
/*
|
||||
* \brief Starts the DHCP client application
|
||||
*/
|
||||
virtual void StartApplication (void);
|
||||
|
||||
/*
|
||||
* \brief Stops the DHCP client application
|
||||
*/
|
||||
virtual void StopApplication (void);
|
||||
|
||||
/*
|
||||
* \brief Handles changes in LinkState
|
||||
*/
|
||||
void LinkStateHandler (void);
|
||||
|
||||
/*
|
||||
* \brief Handles incoming packets from the network
|
||||
* \param socket Socket bound to port 68 of the DHCP client
|
||||
*/
|
||||
void NetHandler (Ptr<Socket> socket);
|
||||
|
||||
/*
|
||||
* \brief Sends DHCP DISCOVER and changes the client state to WAIT_OFFER
|
||||
*/
|
||||
void Boot (void);
|
||||
|
||||
/*
|
||||
* \brief Stores DHCP offers in m_offerList
|
||||
* \param header DhcpHeader of the DHCP OFFER message
|
||||
*/
|
||||
void OfferHandler (DhcpHeader header);
|
||||
|
||||
/*
|
||||
* \brief Selects an OFFER from m_offerList
|
||||
*/
|
||||
void Select (void);
|
||||
|
||||
/*
|
||||
* \brief Sends the DHCP REQUEST message and changes the client state to WAIT_ACK
|
||||
*/
|
||||
void Request (void);
|
||||
|
||||
/*
|
||||
* \brief Receives the DHCP ACK and configures IP address of the client.
|
||||
* It also triggers the timeout, renew and rebind events.
|
||||
* \param header DhcpHeader of the DHCP ACK message
|
||||
* \param from Address of DHCP server that sent the DHCP ACK
|
||||
*/
|
||||
void AcceptAck (DhcpHeader header, Address from);
|
||||
|
||||
/*
|
||||
* \brief Remove the current DHCP information and restart the process
|
||||
*/
|
||||
void RemoveAndStart ();
|
||||
|
||||
uint8_t m_state; //!< State of the DHCP client
|
||||
Ptr<NetDevice> m_device; //!< NetDevice pointer
|
||||
Ptr<Socket> m_socket; //!< Socket for remote communication
|
||||
Ipv4Address m_remoteAddress; //!< Initially set to 255.255.255.255 to start DHCP
|
||||
Ipv4Address m_offeredAddress; //!< Address offered to the client
|
||||
Ipv4Address m_myAddress; //!< Address assigned to the client
|
||||
Address m_chaddr; //!< chaddr of the interface (stored as an Address for convenience).
|
||||
Ipv4Mask m_myMask; //!< Mask of the address assigned
|
||||
Ipv4Address m_server; //!< Address of the DHCP server
|
||||
Ipv4Address m_gateway; //!< Address of the gateway
|
||||
EventId m_requestEvent; //!< Address refresh event
|
||||
EventId m_discoverEvent; //!< Message retransmission event
|
||||
EventId m_refreshEvent; //!< Message refresh event
|
||||
EventId m_rebindEvent; //!< Message rebind event
|
||||
EventId m_nextOfferEvent; //!< Message next offer event
|
||||
EventId m_timeout; //!< The timeout period
|
||||
Time m_lease; //!< Store the lease time of address
|
||||
Time m_renew; //!< Store the renew time of address
|
||||
Time m_rebind; //!< Store the rebind time of address
|
||||
Time m_nextoffer; //!< Time to try the next offer (if request gets no reply)
|
||||
Ptr<RandomVariableStream> m_ran; //!< Uniform random variable for transaction ID
|
||||
Time m_rtrs; //!< Defining the time for retransmission
|
||||
Time m_collect; //!< Time for which client should collect offers
|
||||
bool m_offered; //!< Specify if the client has got any offer
|
||||
std::list<DhcpHeader> m_offerList; //!< Stores all the offers given to the client
|
||||
uint32_t m_tran; //!< Stores the current transaction number to be used
|
||||
TracedCallback<const Ipv4Address&> m_newLease;//!< Trace of new lease
|
||||
TracedCallback<const Ipv4Address&> m_expiry; //!< Trace of lease expire
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* DHCP_CLIENT_H */
|
||||
517
src/internet-apps/model/dhcp-header.cc
Normal file
517
src/internet-apps/model/dhcp-header.cc
Normal file
@@ -0,0 +1,517 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 UPB
|
||||
* Copyright (c) 2017 NITK Surathkal
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Author: Radu Lupu <rlupu@elcom.pub.ro>
|
||||
* Ankit Deepak <adadeepak8@gmail.com>
|
||||
* Deepti Rajagopal <deeptir96@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/header.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "dhcp-header.h"
|
||||
#include "ns3/address-utils.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("DhcpHeader");
|
||||
NS_OBJECT_ENSURE_REGISTERED (DhcpHeader);
|
||||
|
||||
DhcpHeader::DhcpHeader ()
|
||||
{
|
||||
m_hType = 1;
|
||||
m_hLen = 6;
|
||||
m_xid = 0;
|
||||
m_secs = 0;
|
||||
m_hops = 0;
|
||||
m_flags = 0;
|
||||
Ipv4Address addr = Ipv4Address ("0.0.0.0");
|
||||
m_yiAddr = addr;
|
||||
m_ciAddr = addr;
|
||||
m_siAddr = addr;
|
||||
m_giAddr = addr;
|
||||
m_dhcps = addr;
|
||||
m_req = addr;
|
||||
m_route = addr;
|
||||
m_len = 240;
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
m_sname[i] = 0;
|
||||
}
|
||||
for (i = 0; i < 128; i++)
|
||||
{
|
||||
m_file[i] = 0;
|
||||
}
|
||||
m_magic_cookie[0] = 99;
|
||||
m_magic_cookie[1] = 130;
|
||||
m_magic_cookie[2] = 83;
|
||||
m_magic_cookie[3] = 99;
|
||||
}
|
||||
|
||||
DhcpHeader::~DhcpHeader ()
|
||||
{
|
||||
}
|
||||
|
||||
void DhcpHeader::SetType (uint8_t type)
|
||||
{
|
||||
if (m_opt[OP_MSGTYPE] == false)
|
||||
{
|
||||
m_len += 3;
|
||||
m_opt[OP_MSGTYPE] = true;
|
||||
}
|
||||
m_op = type;
|
||||
m_bootp = (m_op == 0||m_op == 2) ? 1 : 2;
|
||||
}
|
||||
|
||||
uint8_t DhcpHeader::GetType (void) const
|
||||
{
|
||||
return m_op;
|
||||
}
|
||||
|
||||
void DhcpHeader::SetHWType (uint8_t htype, uint8_t hlen)
|
||||
{
|
||||
m_hType = htype;
|
||||
m_hLen = hlen;
|
||||
}
|
||||
|
||||
void DhcpHeader::SetTran (uint32_t tran)
|
||||
{
|
||||
m_xid = tran;
|
||||
}
|
||||
|
||||
uint32_t DhcpHeader::GetTran (void) const
|
||||
{
|
||||
return m_xid;
|
||||
}
|
||||
|
||||
void DhcpHeader::SetTime ()
|
||||
{
|
||||
m_secs = (uint16_t) Simulator::Now ().GetSeconds ();
|
||||
}
|
||||
|
||||
void DhcpHeader::SetChaddr (Address addr)
|
||||
{
|
||||
std::memset (m_chaddr, 0, 16);
|
||||
NS_ASSERT_MSG (addr.GetLength () <= 16, "Address length too big");
|
||||
addr.CopyTo (m_chaddr);
|
||||
}
|
||||
|
||||
void DhcpHeader::SetChaddr (uint8_t* addr, uint8_t len)
|
||||
{
|
||||
std::memset (m_chaddr, 0, 16);
|
||||
NS_ASSERT_MSG (len <= 16, "Address length too big");
|
||||
std::memcpy (m_chaddr, addr, len);
|
||||
}
|
||||
|
||||
Address DhcpHeader::GetChaddr ()
|
||||
{
|
||||
Address addr;
|
||||
addr.CopyFrom (m_chaddr, 16);
|
||||
return addr;
|
||||
}
|
||||
|
||||
void DhcpHeader::SetYiaddr (Ipv4Address addr)
|
||||
{
|
||||
m_yiAddr = addr;
|
||||
}
|
||||
|
||||
Ipv4Address DhcpHeader::GetYiaddr (void) const
|
||||
{
|
||||
return m_yiAddr;
|
||||
}
|
||||
|
||||
void DhcpHeader::SetDhcps (Ipv4Address addr)
|
||||
{
|
||||
if (m_opt[OP_SERVID] == false)
|
||||
{
|
||||
m_len += 6;
|
||||
m_opt[OP_SERVID] = true;
|
||||
}
|
||||
m_dhcps = addr;
|
||||
}
|
||||
|
||||
Ipv4Address DhcpHeader::GetDhcps (void) const
|
||||
{
|
||||
return m_dhcps;
|
||||
}
|
||||
|
||||
void DhcpHeader::SetReq (Ipv4Address addr)
|
||||
{
|
||||
if (m_opt[OP_ADDREQ] == false)
|
||||
{
|
||||
m_len += 6;
|
||||
m_opt[OP_ADDREQ] = true;
|
||||
}
|
||||
m_req = addr;
|
||||
}
|
||||
|
||||
Ipv4Address DhcpHeader::GetReq (void) const
|
||||
{
|
||||
return m_req;
|
||||
}
|
||||
|
||||
void DhcpHeader::SetMask (uint32_t addr)
|
||||
{
|
||||
if (m_opt[OP_MASK] == false)
|
||||
{
|
||||
m_len += 6;
|
||||
m_opt[OP_MASK] = true;
|
||||
}
|
||||
m_mask = addr;
|
||||
}
|
||||
|
||||
uint32_t DhcpHeader::GetMask (void) const
|
||||
{
|
||||
return m_mask;
|
||||
}
|
||||
|
||||
void DhcpHeader::SetRouter (Ipv4Address addr)
|
||||
{
|
||||
if (m_opt[OP_ROUTE] == false)
|
||||
{
|
||||
m_len += 6;
|
||||
m_opt[OP_ROUTE] = true;
|
||||
}
|
||||
m_route = addr;
|
||||
}
|
||||
|
||||
Ipv4Address DhcpHeader::GetRouter (void) const
|
||||
{
|
||||
return m_route;
|
||||
}
|
||||
|
||||
void DhcpHeader::SetLease (uint32_t time)
|
||||
{
|
||||
if (m_opt[OP_LEASE] == false)
|
||||
{
|
||||
m_len += 6;
|
||||
m_opt[OP_LEASE] = true;
|
||||
}
|
||||
m_lease = time;
|
||||
}
|
||||
|
||||
uint32_t DhcpHeader::GetLease (void) const
|
||||
{
|
||||
return m_lease;
|
||||
}
|
||||
|
||||
void DhcpHeader::SetRenew (uint32_t time)
|
||||
{
|
||||
if (m_opt[OP_RENEW] == false)
|
||||
{
|
||||
m_len += 6;
|
||||
m_opt[OP_RENEW] = true;
|
||||
}
|
||||
m_renew = time;
|
||||
}
|
||||
|
||||
uint32_t DhcpHeader::GetRenew (void) const
|
||||
{
|
||||
return m_renew;
|
||||
}
|
||||
|
||||
void DhcpHeader::SetRebind (uint32_t time)
|
||||
{
|
||||
if (m_opt[OP_REBIND] == false)
|
||||
{
|
||||
m_len += 6;
|
||||
m_opt[OP_REBIND] = true;
|
||||
}
|
||||
m_rebind = time;
|
||||
}
|
||||
|
||||
uint32_t DhcpHeader::GetRebind (void) const
|
||||
{
|
||||
return m_rebind;
|
||||
}
|
||||
|
||||
void DhcpHeader::ResetOpt ()
|
||||
{
|
||||
m_len = 241;
|
||||
int i;
|
||||
for (i = 0; i < OP_END; i++)
|
||||
{
|
||||
m_opt[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t DhcpHeader::GetSerializedSize (void) const
|
||||
{
|
||||
return m_len;
|
||||
}
|
||||
|
||||
TypeId DhcpHeader::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::DhcpHeader")
|
||||
.SetParent<Header> ()
|
||||
.SetGroupName ("Internet-Apps")
|
||||
.AddConstructor<DhcpHeader> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
TypeId DhcpHeader::GetInstanceTypeId (void) const
|
||||
{
|
||||
return GetTypeId ();
|
||||
}
|
||||
|
||||
void DhcpHeader::Print (std::ostream &os) const
|
||||
{
|
||||
os << "(type=" << m_op << ")";
|
||||
}
|
||||
|
||||
void
|
||||
DhcpHeader::Serialize (Buffer::Iterator start) const
|
||||
{
|
||||
Buffer::Iterator i = start;
|
||||
i.WriteU8 (m_bootp);
|
||||
i.WriteU8 (m_hType);
|
||||
i.WriteU8 (m_hLen);
|
||||
i.WriteU8 (m_hops);
|
||||
i.WriteU32 (m_xid);
|
||||
i.WriteHtonU16 (m_secs);
|
||||
i.WriteU16 ( m_flags);
|
||||
WriteTo (i, m_ciAddr);
|
||||
WriteTo (i, m_yiAddr);
|
||||
WriteTo (i, m_siAddr);
|
||||
WriteTo (i, m_giAddr);
|
||||
i.Write (m_chaddr, 16);
|
||||
i.Write (m_sname,64);
|
||||
i.Write (m_file,128);
|
||||
i.Write (m_magic_cookie,4);
|
||||
if (m_opt[OP_MASK])
|
||||
{
|
||||
i.WriteU8 (OP_MASK);
|
||||
i.WriteU8 (4);
|
||||
i.WriteHtonU32 (m_mask);
|
||||
}
|
||||
if (m_opt[OP_MSGTYPE])
|
||||
{
|
||||
i.WriteU8 (OP_MSGTYPE);
|
||||
i.WriteU8 (1);
|
||||
i.WriteU8 ((m_op + 1));
|
||||
}
|
||||
if (m_opt[OP_ADDREQ])
|
||||
{
|
||||
i.WriteU8 (OP_ADDREQ);
|
||||
i.WriteU8 (4);
|
||||
WriteTo (i, m_req);
|
||||
}
|
||||
if (m_opt[OP_SERVID])
|
||||
{
|
||||
i.WriteU8 (OP_SERVID);
|
||||
i.WriteU8 (4);
|
||||
WriteTo (i, m_dhcps);
|
||||
}
|
||||
if (m_opt[OP_ROUTE])
|
||||
{
|
||||
i.WriteU8 (OP_ROUTE);
|
||||
i.WriteU8 (4);
|
||||
WriteTo (i, m_route);
|
||||
}
|
||||
if (m_opt[OP_LEASE])
|
||||
{
|
||||
i.WriteU8 (OP_LEASE);
|
||||
i.WriteU8 (4);
|
||||
i.WriteHtonU32 (m_lease);
|
||||
}
|
||||
if (m_opt[OP_RENEW])
|
||||
{
|
||||
i.WriteU8 (OP_RENEW);
|
||||
i.WriteU8 (4);
|
||||
i.WriteHtonU32 (m_renew);
|
||||
}
|
||||
if (m_opt[OP_REBIND])
|
||||
{
|
||||
i.WriteU8 (OP_REBIND);
|
||||
i.WriteU8 (4);
|
||||
i.WriteHtonU32 (m_rebind);
|
||||
}
|
||||
i.WriteU8 (OP_END);
|
||||
}
|
||||
|
||||
uint32_t DhcpHeader::Deserialize (Buffer::Iterator start)
|
||||
{
|
||||
uint32_t len, clen = start.GetSize ();
|
||||
if (clen < 240)
|
||||
{
|
||||
NS_LOG_WARN ("Malformed Packet");
|
||||
return 0;
|
||||
}
|
||||
Buffer::Iterator i = start;
|
||||
m_bootp = i.ReadU8 ();
|
||||
m_hType = i.ReadU8 ();
|
||||
m_hLen = i.ReadU8 ();
|
||||
m_hops = i.ReadU8 ();
|
||||
m_xid = i.ReadU32 ();
|
||||
m_secs = i.ReadNtohU16 ();
|
||||
m_flags = i.ReadU16 ();
|
||||
ReadFrom (i, m_ciAddr);
|
||||
ReadFrom (i, m_yiAddr);
|
||||
ReadFrom (i, m_siAddr);
|
||||
ReadFrom (i, m_giAddr);
|
||||
i.Read (m_chaddr, 16);
|
||||
i.Read (m_sname, 64);
|
||||
i.Read (m_file, 128);
|
||||
i.Read (m_magic_cookie, 4);
|
||||
if ( m_magic_cookie[0] != 99 || m_magic_cookie[1] != 130 || m_magic_cookie[2] != 83 || m_magic_cookie[3] != 99)
|
||||
{
|
||||
NS_LOG_WARN ("Malformed Packet");
|
||||
return 0;
|
||||
}
|
||||
len = 240;
|
||||
uint8_t option;
|
||||
bool loop = true;
|
||||
do
|
||||
{
|
||||
if (len + 1 <= clen)
|
||||
{
|
||||
option = i.ReadU8 ();
|
||||
len += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_WARN ("Malformed Packet");
|
||||
return 0;
|
||||
}
|
||||
switch (option)
|
||||
{
|
||||
case OP_MASK:
|
||||
if (len + 5 < clen)
|
||||
{
|
||||
i.ReadU8 ();
|
||||
m_mask = i.ReadNtohU32 ();
|
||||
len += 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_WARN ("Malformed Packet");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case OP_ROUTE:
|
||||
if (len + 5 < clen)
|
||||
{
|
||||
i.ReadU8 ();
|
||||
ReadFrom (i, m_route);
|
||||
len += 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_WARN ("Malformed Packet");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case OP_MSGTYPE:
|
||||
if (len + 2 < clen)
|
||||
{
|
||||
i.ReadU8 ();
|
||||
m_op = (i.ReadU8 () - 1);
|
||||
len += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_WARN ("Malformed Packet");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case OP_SERVID:
|
||||
if (len + 5 < clen)
|
||||
{
|
||||
i.ReadU8 ();
|
||||
ReadFrom (i, m_dhcps);
|
||||
len += 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_WARN ("Malformed Packet");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case OP_ADDREQ:
|
||||
if (len + 5 < clen)
|
||||
{
|
||||
i.ReadU8 ();
|
||||
ReadFrom (i, m_req);
|
||||
len += 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_WARN ("Malformed Packet");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case OP_LEASE:
|
||||
if (len + 5 < clen)
|
||||
{
|
||||
i.ReadU8 ();
|
||||
m_lease = i.ReadNtohU32 ();
|
||||
len += 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_WARN ("Malformed Packet");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case OP_RENEW:
|
||||
if (len + 5 < clen)
|
||||
{
|
||||
i.ReadU8 ();
|
||||
m_renew = i.ReadNtohU32 ();
|
||||
len += 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_WARN ("Malformed Packet");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case OP_REBIND:
|
||||
if (len + 5 < clen)
|
||||
{
|
||||
i.ReadU8 ();
|
||||
m_rebind = i.ReadNtohU32 ();
|
||||
len += 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_WARN ("Malformed Packet");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case OP_END:
|
||||
loop = false;
|
||||
break;
|
||||
default:
|
||||
NS_LOG_WARN ("Malformed Packet");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
while (loop);
|
||||
|
||||
m_len = len;
|
||||
return m_len;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
322
src/internet-apps/model/dhcp-header.h
Normal file
322
src/internet-apps/model/dhcp-header.h
Normal file
@@ -0,0 +1,322 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 UPB
|
||||
* Copyright (c) 2017 NITK Surathkal
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Author: Radu Lupu <rlupu@elcom.pub.ro>
|
||||
* Ankit Deepak <adadeepak8@gmail.com>
|
||||
* Deepti Rajagopal <deeptir96@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DHCP_HEADER_H
|
||||
#define DHCP_HEADER_H
|
||||
|
||||
#include "ns3/header.h"
|
||||
#include <ns3/mac48-address.h>
|
||||
#include <ns3/mac64-address.h>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \ingroup internet-apps
|
||||
* \defgroup dhcp DHCPv4 Client and Server
|
||||
*/
|
||||
|
||||
/**
|
||||
* \ingroup dhcp
|
||||
*
|
||||
* \class DhcpHeader
|
||||
* \brief BOOTP header with DHCP messages supports the following options:
|
||||
* Subnet Mask (1), Address Request (50), Refresh Lease Time (51),
|
||||
* DHCP Message Type (53), DHCP Server ID (54), Renew Time (58),
|
||||
* Rebind Time (59) and End (255) of BOOTP
|
||||
|
||||
\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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| op (1) | htype (1) | hlen (1) | hops (1) |
|
||||
+---------------+---------------+---------------+---------------+
|
||||
| xid (4) |
|
||||
+-------------------------------+-------------------------------+
|
||||
| secs (2) | flags (2) |
|
||||
+-------------------------------+-------------------------------+
|
||||
| ciaddr (4) |
|
||||
+---------------------------------------------------------------+
|
||||
| yiaddr (4) |
|
||||
+---------------------------------------------------------------+
|
||||
| siaddr (4) |
|
||||
+---------------------------------------------------------------+
|
||||
| giaddr (4) |
|
||||
+---------------------------------------------------------------+
|
||||
| |
|
||||
| chaddr (16) |
|
||||
| |
|
||||
| |
|
||||
+---------------------------------------------------------------+
|
||||
| |
|
||||
| sname (64) |
|
||||
+---------------------------------------------------------------+
|
||||
| |
|
||||
| file (128) |
|
||||
+---------------------------------------------------------------+
|
||||
| |
|
||||
| options (variable) |
|
||||
+---------------------------------------------------------------+
|
||||
\endverbatim
|
||||
|
||||
*/
|
||||
class DhcpHeader : public Header
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* \brief Constructor
|
||||
*/
|
||||
DhcpHeader ();
|
||||
|
||||
/**
|
||||
* \brief Destructor
|
||||
*/
|
||||
~DhcpHeader ();
|
||||
|
||||
enum Options
|
||||
{
|
||||
OP_MASK = 1, //!< BOOTP Option 1: Address Mask
|
||||
OP_ROUTE = 3, //!< BOOTP Option 3: Router Option
|
||||
OP_ADDREQ = 50, //!< BOOTP Option 50: Requested Address
|
||||
OP_LEASE = 51, //!< BOOTP Option 51: Address Lease Time
|
||||
OP_MSGTYPE = 53, //!< BOOTP Option 53: DHCP Message Type
|
||||
OP_SERVID = 54, //!< BOOTP Option 54: Server Identifier
|
||||
OP_RENEW = 58, //!< BOOTP Option 58: Address Renewal Time
|
||||
OP_REBIND = 59, //!< BOOTP Option 59: Address Rebind Time
|
||||
OP_END = 255 //!< BOOTP Option 255: END
|
||||
};
|
||||
|
||||
enum Messages
|
||||
{
|
||||
DHCPDISCOVER = 0, //!< Code for DHCP Discover
|
||||
DHCPOFFER = 1, //!< Code for DHCP Offer
|
||||
DHCPREQ = 2, //!< Code for DHCP Request
|
||||
DHCPACK = 4, //!< Code for DHCP ACK
|
||||
DHCPNACK = 5 //!< Code for DHCP NACK
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Set the type of BOOTP and DHCP messages
|
||||
* \param type The type of message
|
||||
*/
|
||||
void SetType (uint8_t type);
|
||||
|
||||
/**
|
||||
* \brief Return the type of DHCP message
|
||||
* \return The type of message
|
||||
*/
|
||||
uint8_t GetType (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the hardware information
|
||||
* \param htype Hardware type
|
||||
* \param hlen Hardware length
|
||||
*/
|
||||
void SetHWType (uint8_t htype, uint8_t hlen);
|
||||
|
||||
/**
|
||||
* \brief Set the transaction ID
|
||||
* \param tran The transaction number
|
||||
*/
|
||||
void SetTran (uint32_t tran);
|
||||
|
||||
/**
|
||||
* \brief Get the transaction id
|
||||
* \return The transaction id
|
||||
*/
|
||||
uint32_t GetTran (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the time when message is sent
|
||||
*/
|
||||
void SetTime ();
|
||||
|
||||
/**
|
||||
* \brief Set the Address of the device.
|
||||
*
|
||||
* Only the relevant bits are considered (i.e., not the type and length)
|
||||
*
|
||||
* \param addr Address of the device
|
||||
*/
|
||||
void SetChaddr (Address addr);
|
||||
|
||||
/**
|
||||
* \brief Set the Address of the device
|
||||
* \param addr Address of the device
|
||||
* \param len Address length
|
||||
*/
|
||||
void SetChaddr (uint8_t* addr, uint8_t len);
|
||||
|
||||
/**
|
||||
* \brief Get the Address of the client.
|
||||
*
|
||||
* Note: the address is always 16-bytes long.
|
||||
*
|
||||
* \return Address of the client
|
||||
*/
|
||||
Address GetChaddr (void);
|
||||
|
||||
/**
|
||||
* \brief Set the IPv4Address of the client
|
||||
* \param addr The client Ipv4Address
|
||||
*/
|
||||
void SetYiaddr (Ipv4Address addr);
|
||||
|
||||
/**
|
||||
* \brief Get the IPv4Address of the client
|
||||
* \return IPv4Address of the client
|
||||
*/
|
||||
Ipv4Address GetYiaddr (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the DHCP server information
|
||||
* \param addr IPv4Address of the server
|
||||
*/
|
||||
void SetDhcps (Ipv4Address addr);
|
||||
|
||||
/**
|
||||
* \brief Get the information about the DHCP server
|
||||
* \return IPv4Address of DHCP server
|
||||
*/
|
||||
Ipv4Address GetDhcps (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the Ipv4Address requested by the client
|
||||
* \param addr Ipv4Address requested by the client
|
||||
*/
|
||||
void SetReq (Ipv4Address addr);
|
||||
|
||||
/**
|
||||
* \brief Get the IPv4Address requested by the client
|
||||
* \return IPv4Address requested by the client
|
||||
*/
|
||||
Ipv4Address GetReq (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the mask of the IPv4Address
|
||||
* \param addr 32 bit mask
|
||||
*/
|
||||
void SetMask (uint32_t addr);
|
||||
|
||||
/**
|
||||
* \brief Return the mask of the network
|
||||
* \return 32 bit mask
|
||||
*/
|
||||
uint32_t GetMask (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the Ipv4Address of gateway to be used
|
||||
* \param addr The Ipv4Address of the gateway
|
||||
*/
|
||||
void SetRouter (Ipv4Address addr);
|
||||
|
||||
/**
|
||||
* \brief Return the Ipv4Address of gateway to be used
|
||||
* \return The Ipv4Address of the gateway
|
||||
*/
|
||||
Ipv4Address GetRouter (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the lease time of the IPv4Address
|
||||
* \param time 32 bit time
|
||||
*/
|
||||
void SetLease (uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Return the lease time of the IPv4Address
|
||||
* \return 32 bit time
|
||||
*/
|
||||
uint32_t GetLease (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the Renewal time of the IPv4Address
|
||||
* \param time 32 bit time
|
||||
*/
|
||||
void SetRenew (uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Return the Renewal time of the address
|
||||
* \return 32 bit time
|
||||
*/
|
||||
uint32_t GetRenew (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the Rebind time of the IPv4Address
|
||||
* \param time 32 bit time
|
||||
*/
|
||||
void SetRebind (uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Return the Rebind time of the address
|
||||
* \return 32 bit time
|
||||
*/
|
||||
uint32_t GetRebind (void) const;
|
||||
|
||||
/**
|
||||
* \brief Reset the BOOTP options
|
||||
*/
|
||||
void ResetOpt ();
|
||||
|
||||
private:
|
||||
virtual TypeId GetInstanceTypeId (void) const;
|
||||
virtual void Print (std::ostream &os) const;
|
||||
virtual uint32_t GetSerializedSize (void) const;
|
||||
virtual void Serialize (Buffer::Iterator start) const;
|
||||
virtual uint32_t Deserialize (Buffer::Iterator start);
|
||||
|
||||
uint8_t m_op; //!< The DHCP Message type
|
||||
uint8_t m_bootp; //!< The BOOTP Message type
|
||||
uint8_t m_hType; //!< The hardware type
|
||||
uint8_t m_hLen; //!< The hardware length
|
||||
uint8_t m_hops; //!< The number of hops covered by the message
|
||||
uint32_t m_xid; //!< The transaction number
|
||||
uint32_t m_mask; //!< The mask of the network
|
||||
uint32_t m_len; //!< The length of the header
|
||||
uint16_t m_secs; //!< Seconds elapsed
|
||||
uint16_t m_flags; //!< BOOTP flags
|
||||
uint8_t m_chaddr[16]; //!< The address identifier
|
||||
Ipv4Address m_yiAddr; //!< Your (client) IP address
|
||||
Ipv4Address m_ciAddr; //!< The IP address of the client
|
||||
Ipv4Address m_siAddr; //!< Next Server IP address
|
||||
Ipv4Address m_giAddr; //!< Relay Agent IP address
|
||||
Ipv4Address m_dhcps; //!< DHCP server IP address
|
||||
Ipv4Address m_req; //!< Requested Address
|
||||
Ipv4Address m_route; //!< Router Option Address
|
||||
uint8_t m_sname[64]; //!< Server name (Padded for now)
|
||||
uint8_t m_file[128]; //!< File name (Padded for now)
|
||||
uint8_t m_magic_cookie[4]; //!< DHCP Magic Cookie
|
||||
uint32_t m_lease; //!< The lease time of the address
|
||||
uint32_t m_renew; //!< The renewal time for the client
|
||||
uint32_t m_rebind; //!< The rebinding time for the client
|
||||
bool m_opt[255]; //!< BOOTP option list
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* DHCP_HEADER_H */
|
||||
421
src/internet-apps/model/dhcp-server.cc
Normal file
421
src/internet-apps/model/dhcp-server.cc
Normal file
@@ -0,0 +1,421 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 UPB
|
||||
* Copyright (c) 2017 NITK Surathkal
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Author: Radu Lupu <rlupu@elcom.pub.ro>
|
||||
* Ankit Deepak <adadeepak8@gmail.com>
|
||||
* Deepti Rajagopal <deeptir96@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/ipv4-packet-info-tag.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/socket-factory.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/config.h"
|
||||
#include "dhcp-server.h"
|
||||
#include "dhcp-header.h"
|
||||
#include "ns3/ipv4.h"
|
||||
#include <map>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("DhcpServer");
|
||||
NS_OBJECT_ENSURE_REGISTERED (DhcpServer);
|
||||
|
||||
TypeId
|
||||
DhcpServer::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::DhcpServer")
|
||||
.SetParent<Application> ()
|
||||
.AddConstructor<DhcpServer> ()
|
||||
.SetGroupName ("Internet-Apps")
|
||||
.AddAttribute ("LeaseTime",
|
||||
"Lease for which address will be leased.",
|
||||
TimeValue (Seconds (30)),
|
||||
MakeTimeAccessor (&DhcpServer::m_lease),
|
||||
MakeTimeChecker ())
|
||||
.AddAttribute ("RenewTime",
|
||||
"Time after which client should renew.",
|
||||
TimeValue (Seconds (15)),
|
||||
MakeTimeAccessor (&DhcpServer::m_renew),
|
||||
MakeTimeChecker ())
|
||||
.AddAttribute ("RebindTime",
|
||||
"Time after which client should rebind.",
|
||||
TimeValue (Seconds (25)),
|
||||
MakeTimeAccessor (&DhcpServer::m_rebind),
|
||||
MakeTimeChecker ())
|
||||
.AddAttribute ("PoolAddresses",
|
||||
"Pool of addresses to provide on request.",
|
||||
Ipv4AddressValue (),
|
||||
MakeIpv4AddressAccessor (&DhcpServer::m_poolAddress),
|
||||
MakeIpv4AddressChecker ())
|
||||
.AddAttribute ("FirstAddress",
|
||||
"The First valid address that can be given.",
|
||||
Ipv4AddressValue (),
|
||||
MakeIpv4AddressAccessor (&DhcpServer::m_minAddress),
|
||||
MakeIpv4AddressChecker ())
|
||||
.AddAttribute ("LastAddress",
|
||||
"The Last valid address that can be given.",
|
||||
Ipv4AddressValue (),
|
||||
MakeIpv4AddressAccessor (&DhcpServer::m_maxAddress),
|
||||
MakeIpv4AddressChecker ())
|
||||
.AddAttribute ("PoolMask",
|
||||
"Mask of the pool of addresses.",
|
||||
Ipv4MaskValue (),
|
||||
MakeIpv4MaskAccessor (&DhcpServer::m_poolMask),
|
||||
MakeIpv4MaskChecker ())
|
||||
.AddAttribute ("Gateway",
|
||||
"Address of default gateway",
|
||||
Ipv4AddressValue (),
|
||||
MakeIpv4AddressAccessor (&DhcpServer::m_gateway),
|
||||
MakeIpv4AddressChecker ())
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
DhcpServer::DhcpServer ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
DhcpServer::~DhcpServer ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
void
|
||||
DhcpServer::DoDispose (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
Application::DoDispose ();
|
||||
}
|
||||
|
||||
void DhcpServer::StartApplication (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
NS_ASSERT_MSG (m_minAddress < m_maxAddress,"Invalid Address range");
|
||||
|
||||
Ipv4Address myOwnAddress;
|
||||
|
||||
if (m_socket)
|
||||
{
|
||||
NS_ABORT_MSG ("DHCP daemon is not (yet) meant to be started twice or more.");
|
||||
}
|
||||
|
||||
uint32_t addrIndex;
|
||||
|
||||
//add the DHCP local address to the leased addresses list, if it is defined!
|
||||
Ptr<Ipv4> ipv4 = GetNode ()->GetObject<Ipv4> ();
|
||||
int32_t ifIndex = ipv4->GetInterfaceForPrefix (m_poolAddress, m_poolMask);
|
||||
|
||||
if (ifIndex < 0)
|
||||
{
|
||||
NS_ABORT_MSG ("DHCP daemon must be run on the same subnet it is assigning the addresses.");
|
||||
}
|
||||
|
||||
for (addrIndex = 0; addrIndex < ipv4->GetNAddresses (ifIndex); addrIndex++)
|
||||
{
|
||||
if (ipv4->GetAddress (ifIndex, addrIndex).GetLocal ().CombineMask (m_poolMask) == m_poolAddress &&
|
||||
ipv4->GetAddress (ifIndex, addrIndex).GetLocal ().Get () >= m_minAddress.Get () &&
|
||||
ipv4->GetAddress (ifIndex, addrIndex).GetLocal ().Get () <= m_maxAddress.Get ())
|
||||
{
|
||||
// set infinite GRANTED_LEASED_TIME for my address
|
||||
|
||||
myOwnAddress = ipv4->GetAddress (ifIndex, addrIndex).GetLocal ();
|
||||
m_leasedAddresses[Address ()] = std::make_pair (myOwnAddress, 0xffffffff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
|
||||
m_socket = Socket::CreateSocket (GetNode (), tid);
|
||||
InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), PORT);
|
||||
m_socket->SetAllowBroadcast (true);
|
||||
m_socket->Bind (local);
|
||||
m_socket->BindToNetDevice (ipv4->GetNetDevice (ifIndex));
|
||||
m_socket->SetRecvPktInfo (true);
|
||||
|
||||
uint32_t range = m_maxAddress.Get () - m_minAddress.Get () + 1;
|
||||
for (uint32_t searchSeq = 0; searchSeq < range; searchSeq ++)
|
||||
{
|
||||
Ipv4Address poolAddress = Ipv4Address (m_minAddress.Get () + searchSeq);
|
||||
if (poolAddress != myOwnAddress)
|
||||
{
|
||||
NS_LOG_LOGIC ("Adding " << poolAddress << " to the pool");
|
||||
m_availableAddresses.push_back (poolAddress);
|
||||
}
|
||||
}
|
||||
|
||||
m_socket->SetRecvCallback (MakeCallback (&DhcpServer::NetHandler, this));
|
||||
m_expiredEvent = Simulator::Schedule (Seconds (1), &DhcpServer::TimerHandler, this);
|
||||
}
|
||||
|
||||
void DhcpServer::StopApplication ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
if (m_socket != 0)
|
||||
{
|
||||
m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
|
||||
}
|
||||
|
||||
m_leasedAddresses.clear ();
|
||||
Simulator::Remove (m_expiredEvent);
|
||||
}
|
||||
|
||||
void DhcpServer::TimerHandler ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// Set up timeout events and release of unsolicited addresses from the list
|
||||
LeasedAddressIter i;
|
||||
for (i = m_leasedAddresses.begin (); i != m_leasedAddresses.end (); i++)
|
||||
{
|
||||
// update the address state
|
||||
if (i->second.second != 0xffffffff && i->second.second != 0)
|
||||
{
|
||||
i->second.second--;
|
||||
if (i->second.second == 0)
|
||||
{
|
||||
NS_LOG_INFO ("Address leased state expired, address removed - " <<
|
||||
"chaddr: " << i->first <<
|
||||
"IP address " << i->second.first);
|
||||
i->second.second = 0;
|
||||
m_expiredAddresses.push_front (i->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_expiredEvent = Simulator::Schedule (Seconds (1), &DhcpServer::TimerHandler, this);
|
||||
}
|
||||
|
||||
void DhcpServer::NetHandler (Ptr<Socket> socket)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << socket);
|
||||
|
||||
DhcpHeader header;
|
||||
Ptr<Packet> packet = 0;
|
||||
Address from;
|
||||
packet = m_socket->RecvFrom (from);
|
||||
|
||||
InetSocketAddress senderAddr = InetSocketAddress::ConvertFrom (from);
|
||||
|
||||
Ipv4PacketInfoTag interfaceInfo;
|
||||
if (!packet->RemovePacketTag (interfaceInfo))
|
||||
{
|
||||
NS_ABORT_MSG ("No incoming interface on DHCP message, aborting.");
|
||||
}
|
||||
uint32_t incomingIf = interfaceInfo.GetRecvIf ();
|
||||
Ptr<NetDevice> iDev = GetNode ()->GetDevice (incomingIf);
|
||||
|
||||
if (packet->RemoveHeader (header) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (header.GetType () == DhcpHeader::DHCPDISCOVER)
|
||||
{
|
||||
SendOffer (iDev, header, senderAddr);
|
||||
}
|
||||
if (header.GetType () == DhcpHeader::DHCPREQ && (header.GetReq ()).Get () >= m_minAddress.Get () && (header.GetReq ()).Get () <= m_maxAddress.Get ())
|
||||
{
|
||||
SendAck (iDev, header, senderAddr);
|
||||
}
|
||||
}
|
||||
|
||||
void DhcpServer::SendOffer (Ptr<NetDevice> iDev, DhcpHeader header, InetSocketAddress from)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << iDev << header << from);
|
||||
|
||||
DhcpHeader newDhcpHeader;
|
||||
Address sourceChaddr = header.GetChaddr ();
|
||||
uint32_t tran = header.GetTran ();
|
||||
Ptr<Packet> packet = 0;
|
||||
bool found = false;
|
||||
Ipv4Address offeredAddress;
|
||||
|
||||
NS_LOG_INFO ("DHCP DISCOVER from: " << from.GetIpv4 () << " source port: " << from.GetPort ());
|
||||
|
||||
LeasedAddressIter iter = m_leasedAddresses.find (sourceChaddr);
|
||||
if (iter != m_leasedAddresses.end ())
|
||||
{
|
||||
// We know this client from some time ago
|
||||
if (m_leasedAddresses[sourceChaddr].second != 0 && m_leasedAddresses[sourceChaddr].second != 0xffffffff)
|
||||
{
|
||||
NS_LOG_LOGIC ("This client is sending a DISCOVER but it has still a lease active - perhaps it didn't shut down gracefully: " << sourceChaddr);
|
||||
}
|
||||
|
||||
m_expiredAddresses.remove (sourceChaddr);
|
||||
offeredAddress = m_leasedAddresses[sourceChaddr].first;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// No previous record of the client, we must find a suitable address and create a record.
|
||||
if (!m_availableAddresses.empty ())
|
||||
{
|
||||
// use an address never used before (if there is one)
|
||||
found = true;
|
||||
offeredAddress = m_availableAddresses.front ();
|
||||
m_availableAddresses.pop_front ();
|
||||
}
|
||||
else
|
||||
{
|
||||
// there's still hope: reuse the old ones.
|
||||
if (!m_expiredAddresses.empty ())
|
||||
{
|
||||
Address oldestChaddr = m_expiredAddresses.back ();
|
||||
m_expiredAddresses.pop_back ();
|
||||
offeredAddress = m_leasedAddresses[oldestChaddr].first;
|
||||
m_leasedAddresses.erase (oldestChaddr);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (offeredAddress != Ipv4Address ())
|
||||
{
|
||||
m_leasedAddresses[sourceChaddr] = std::make_pair (offeredAddress, m_lease.GetSeconds ());
|
||||
|
||||
packet = Create<Packet> ();
|
||||
newDhcpHeader.ResetOpt ();
|
||||
newDhcpHeader.SetType (DhcpHeader::DHCPOFFER);
|
||||
newDhcpHeader.SetChaddr (sourceChaddr);
|
||||
newDhcpHeader.SetYiaddr (offeredAddress);
|
||||
|
||||
Ptr<Ipv4> ipv4 = GetNode ()->GetObject<Ipv4> ();
|
||||
Ipv4Address myAddress = ipv4->SelectSourceAddress (iDev, offeredAddress, Ipv4InterfaceAddress::InterfaceAddressScope_e::GLOBAL);
|
||||
|
||||
newDhcpHeader.SetDhcps (myAddress);
|
||||
newDhcpHeader.SetMask (m_poolMask.Get ());
|
||||
newDhcpHeader.SetTran (tran);
|
||||
newDhcpHeader.SetLease (m_lease.GetSeconds ());
|
||||
newDhcpHeader.SetRenew (m_renew.GetSeconds ());
|
||||
newDhcpHeader.SetRebind (m_rebind.GetSeconds ());
|
||||
newDhcpHeader.SetTime ();
|
||||
if (m_gateway != Ipv4Address ())
|
||||
{
|
||||
newDhcpHeader.SetRouter (m_gateway);
|
||||
}
|
||||
packet->AddHeader (newDhcpHeader);
|
||||
|
||||
if ((m_socket->SendTo (packet, 0, InetSocketAddress (Ipv4Address ("255.255.255.255"), from.GetPort ()))) >= 0)
|
||||
{
|
||||
NS_LOG_INFO ("DHCP OFFER" << " Offered Address: " << offeredAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_INFO ("Error while sending DHCP OFFER");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DhcpServer::SendAck (Ptr<NetDevice> iDev, DhcpHeader header, InetSocketAddress from)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << iDev << header << from);
|
||||
|
||||
DhcpHeader newDhcpHeader;
|
||||
Address sourceChaddr = header.GetChaddr ();
|
||||
uint32_t tran = header.GetTran ();
|
||||
Ptr<Packet> packet = 0;
|
||||
Ipv4Address address = header.GetReq ();
|
||||
|
||||
NS_LOG_INFO ("DHCP REQUEST from: " << from.GetIpv4 () <<
|
||||
" source port: " << from.GetPort () <<
|
||||
" - refreshed addr: " << address);
|
||||
|
||||
LeasedAddressIter iter;
|
||||
iter = m_leasedAddresses.find (sourceChaddr);
|
||||
if (iter != m_leasedAddresses.end ())
|
||||
{
|
||||
// update the lease time of this address - send ACK
|
||||
(iter->second.second) += m_lease.GetSeconds ();
|
||||
packet = Create<Packet> ();
|
||||
newDhcpHeader.ResetOpt ();
|
||||
newDhcpHeader.SetType (DhcpHeader::DHCPACK);
|
||||
newDhcpHeader.SetChaddr (sourceChaddr);
|
||||
newDhcpHeader.SetYiaddr (address);
|
||||
newDhcpHeader.SetTran (tran);
|
||||
newDhcpHeader.SetTime ();
|
||||
packet->AddHeader (newDhcpHeader);
|
||||
if (from.GetIpv4 () != address)
|
||||
{
|
||||
m_socket->SendTo (packet, 0, InetSocketAddress (Ipv4Address ("255.255.255.255"), from.GetPort ()));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_socket->SendTo (packet, 0, from);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Deleted or expired lease - send NACK
|
||||
packet = Create<Packet> ();
|
||||
newDhcpHeader.ResetOpt ();
|
||||
newDhcpHeader.SetType (DhcpHeader::DHCPNACK);
|
||||
newDhcpHeader.SetChaddr (sourceChaddr);
|
||||
newDhcpHeader.SetYiaddr (address);
|
||||
newDhcpHeader.SetTran (tran);
|
||||
newDhcpHeader.SetTime ();
|
||||
packet->AddHeader (newDhcpHeader);
|
||||
if (from.GetIpv4 () != address)
|
||||
{
|
||||
m_socket->SendTo (packet, 0, InetSocketAddress (Ipv4Address ("255.255.255.255"), from.GetPort ()));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_socket->SendTo (packet, 0, from);
|
||||
}
|
||||
NS_LOG_INFO ("IP addr does not exists or released!");
|
||||
}
|
||||
}
|
||||
|
||||
void DhcpServer::AddStaticDhcpEntry (Address chaddr, Ipv4Address addr)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << chaddr << addr);
|
||||
Address cleanedCaddr;
|
||||
|
||||
NS_ASSERT_MSG (addr.Get () >= m_minAddress.Get () && addr.Get () <= m_maxAddress.Get (),
|
||||
"Required address is not in the pool " << addr << " is not in [" << m_minAddress << ", " << m_maxAddress << "]");
|
||||
|
||||
// We need to cleanup the type from the stored chaddr, or later we'll fail to compare it.
|
||||
// Moreover, the length is always 16, because chaddr is 16 bytes.
|
||||
uint8_t buffer[Address::MAX_SIZE];
|
||||
std::memset (buffer, 0, Address::MAX_SIZE);
|
||||
uint32_t len = chaddr.CopyTo (buffer);
|
||||
NS_ASSERT_MSG (len <= 16, "DHCP server can not handle a chaddr larger than 16 bytes");
|
||||
cleanedCaddr.CopyFrom (buffer, 16);
|
||||
|
||||
NS_ASSERT_MSG (m_leasedAddresses.find (cleanedCaddr) == m_leasedAddresses.end (),
|
||||
"Client has already an active lease: " << m_leasedAddresses[cleanedCaddr].first);
|
||||
|
||||
AvailableAddress::iterator it = find (m_availableAddresses.begin (), m_availableAddresses.end (), addr);
|
||||
NS_ASSERT_MSG (it == m_availableAddresses.end (),
|
||||
"Required address is not available (perhaps it has been already assigned): " << addr);
|
||||
|
||||
m_availableAddresses.remove (addr);
|
||||
m_leasedAddresses[cleanedCaddr] = std::make_pair (addr, 0xffffffff);
|
||||
}
|
||||
|
||||
} // Namespace ns3
|
||||
147
src/internet-apps/model/dhcp-server.h
Normal file
147
src/internet-apps/model/dhcp-server.h
Normal file
@@ -0,0 +1,147 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 UPB
|
||||
* Copyright (c) 2017 NITK Surathkal
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Author: Radu Lupu <rlupu@elcom.pub.ro>
|
||||
* Ankit Deepak <adadeepak8@gmail.com>
|
||||
* Deepti Rajagopal <deeptir96@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DHCP_SERVER_H
|
||||
#define DHCP_SERVER_H
|
||||
|
||||
#include "ns3/application.h"
|
||||
#include "ns3/event-id.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/address.h"
|
||||
#include "ns3/traced-value.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "dhcp-header.h"
|
||||
#include <map>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class Socket;
|
||||
class Packet;
|
||||
|
||||
/**
|
||||
* \ingroup dhcp
|
||||
*
|
||||
* \class DhcpServer
|
||||
* \brief Implements the functionality of a DHCP server
|
||||
*/
|
||||
class DhcpServer : public Application
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
DhcpServer ();
|
||||
virtual ~DhcpServer ();
|
||||
|
||||
/**
|
||||
* \brief Add a static entry to the pool.
|
||||
*
|
||||
* \param chaddr The client chaddr.
|
||||
* \param addr The address to handle to the client.
|
||||
*/
|
||||
void AddStaticDhcpEntry (Address chaddr, Ipv4Address addr);
|
||||
|
||||
|
||||
protected:
|
||||
virtual void DoDispose (void);
|
||||
|
||||
private:
|
||||
static const int PORT = 67; //!< Port number of DHCP server
|
||||
|
||||
/*
|
||||
* \brief Handles incoming packets from the network
|
||||
* \param socket Socket bound to port 67 of the DHCP server
|
||||
*/
|
||||
void NetHandler (Ptr<Socket> socket);
|
||||
|
||||
/*
|
||||
* \brief Sends DHCP offer after receiving DHCP Discover
|
||||
* \param iDev incoming NetDevice
|
||||
* \param header DHCP header of the received message
|
||||
* \param from Address of the DHCP client
|
||||
*/
|
||||
void SendOffer (Ptr<NetDevice> iDev, DhcpHeader header, InetSocketAddress from);
|
||||
|
||||
/*
|
||||
* \brief Sends DHCP ACK (or NACK) after receiving Request
|
||||
* \param iDev incoming NetDevice
|
||||
* \param header DHCP header of the received message
|
||||
* \param from Address of the DHCP client
|
||||
*/
|
||||
void SendAck (Ptr<NetDevice> iDev, DhcpHeader header, InetSocketAddress from);
|
||||
|
||||
/*
|
||||
* \brief Modifies the remaining lease time of addresses
|
||||
*/
|
||||
void TimerHandler (void);
|
||||
|
||||
/*
|
||||
* \brief Starts the DHCP Server application
|
||||
*/
|
||||
virtual void StartApplication (void);
|
||||
|
||||
/*
|
||||
* \brief Stops the DHCP client application
|
||||
*/
|
||||
virtual void StopApplication (void);
|
||||
|
||||
Ptr<Socket> m_socket; //!< The socket bound to port 67
|
||||
Ipv4Address m_poolAddress; //!< The network address available to the server
|
||||
Ipv4Address m_minAddress; //!< The first address in the address pool
|
||||
Ipv4Address m_maxAddress; //!< The last address in the address pool
|
||||
Ipv4Mask m_poolMask; //!< The network mask of the pool
|
||||
Ipv4Address m_gateway; //!< The gateway address
|
||||
|
||||
/// Leased address container - chaddr + IP addr / lease time
|
||||
typedef std::map<Address, std::pair<Ipv4Address, uint32_t> > LeasedAddress;
|
||||
/// Leased address iterator - chaddr + IP addr / lease time
|
||||
typedef std::map<Address, std::pair<Ipv4Address, uint32_t> >::iterator LeasedAddressIter;
|
||||
/// Leased address const iterator - chaddr + IP addr / lease time
|
||||
typedef std::map<Address, std::pair<Ipv4Address, uint32_t> >::const_iterator LeasedAddressCIter;
|
||||
|
||||
/// Expired address container - chaddr
|
||||
typedef std::list<Address> ExpiredAddress;
|
||||
/// Expired address iterator - chaddr
|
||||
typedef std::list<Address>::iterator ExpiredAddressIter;
|
||||
/// Expired address const iterator - chaddr
|
||||
typedef std::list<Address>::const_iterator ExpiredAddressCIter;
|
||||
|
||||
/// Available address container - IP addr
|
||||
typedef std::list<Ipv4Address> AvailableAddress;
|
||||
|
||||
LeasedAddress m_leasedAddresses; //!< Leased address and their status (cache memory)
|
||||
ExpiredAddress m_expiredAddresses; //!< Expired addresses to be reused (chaddr of the clients)
|
||||
AvailableAddress m_availableAddresses; //!< Available addresses to be used (IP addresses)
|
||||
Time m_lease; //!< The granted lease time for an address
|
||||
Time m_renew; //!< The renewal time for an address
|
||||
Time m_rebind; //!< The rebinding time for an address
|
||||
EventId m_expiredEvent; //!< The Event to trigger TimerHandler
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* DHCP_SERVER_H */
|
||||
162
src/internet-apps/test/dhcp-test.cc
Normal file
162
src/internet-apps/test/dhcp-test.cc
Normal file
@@ -0,0 +1,162 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2017 NITK Surathkal
|
||||
*
|
||||
* 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: Ankit Deepak <adadeepak8@gmail.com>
|
||||
* Deepti Rajagopal <deeptir96@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ns3/data-rate.h"
|
||||
#include "ns3/simple-net-device.h"
|
||||
#include "ns3/simple-net-device-helper.h"
|
||||
#include "ns3/internet-stack-helper.h"
|
||||
#include "ns3/ipv4-address-helper.h"
|
||||
#include "ns3/dhcp-client.h"
|
||||
#include "ns3/dhcp-server.h"
|
||||
#include "ns3/dhcp-helper.h"
|
||||
#include "ns3/test.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
/**
|
||||
* \ingroup dhcp
|
||||
* \defgroup dhcp-test DHCP module tests
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup dhcp-test
|
||||
* \ingroup tests
|
||||
*
|
||||
* \brief DHCP basic tests
|
||||
*/
|
||||
class DhcpTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
DhcpTestCase ();
|
||||
virtual ~DhcpTestCase ();
|
||||
/**
|
||||
* Triggered by an address lease on a client.
|
||||
* \param newAddress The leased address.
|
||||
*/
|
||||
void LeaseObtained (std::string context, const Ipv4Address& newAddress);
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
Ipv4Address m_leasedAddress[3]; //!< Address given to the nodes
|
||||
};
|
||||
|
||||
DhcpTestCase::DhcpTestCase ()
|
||||
: TestCase ("Dhcp test case ")
|
||||
{
|
||||
}
|
||||
|
||||
DhcpTestCase::~DhcpTestCase ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
DhcpTestCase::LeaseObtained (std::string context, const Ipv4Address& newAddress)
|
||||
{
|
||||
uint8_t numericalContext = std::stoi (context, nullptr, 10);
|
||||
|
||||
if (numericalContext >=0 && numericalContext <=2)
|
||||
{
|
||||
m_leasedAddress[numericalContext] = newAddress;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DhcpTestCase::DoRun (void)
|
||||
{
|
||||
/*Set up devices*/
|
||||
NodeContainer nodes;
|
||||
NodeContainer routers;
|
||||
nodes.Create (3);
|
||||
routers.Create (1);
|
||||
|
||||
NodeContainer net (routers, nodes);
|
||||
|
||||
SimpleNetDeviceHelper simpleNetDevice;
|
||||
simpleNetDevice.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
|
||||
simpleNetDevice.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("5Mbps")));
|
||||
NetDeviceContainer devNet = simpleNetDevice.Install (net);
|
||||
|
||||
InternetStackHelper tcpip;
|
||||
tcpip.Install (routers);
|
||||
tcpip.Install (nodes);
|
||||
|
||||
DhcpHelper dhcpHelper;
|
||||
|
||||
ApplicationContainer dhcpServerApp = dhcpHelper.InstallDhcpServer (devNet.Get (0), Ipv4Address ("172.30.0.12"),
|
||||
Ipv4Address ("172.30.0.0"), Ipv4Mask ("/24"),
|
||||
Ipv4Address ("172.30.0.10"), Ipv4Address ("172.30.0.15"),
|
||||
Ipv4Address ("172.30.0.17"));
|
||||
dhcpServerApp.Start (Seconds (0.0));
|
||||
dhcpServerApp.Stop (Seconds (20.0));
|
||||
|
||||
DynamicCast<DhcpServer> (dhcpServerApp.Get (0))->AddStaticDhcpEntry (devNet.Get (3)->GetAddress (), Ipv4Address ("172.30.0.14"));
|
||||
|
||||
NetDeviceContainer dhcpClientNetDevs;
|
||||
dhcpClientNetDevs.Add (devNet.Get (1));
|
||||
dhcpClientNetDevs.Add (devNet.Get (2));
|
||||
dhcpClientNetDevs.Add (devNet.Get (3));
|
||||
|
||||
ApplicationContainer dhcpClientApps = dhcpHelper.InstallDhcpClient (dhcpClientNetDevs);
|
||||
dhcpClientApps.Start (Seconds (1.0));
|
||||
dhcpClientApps.Stop (Seconds (20.0));
|
||||
|
||||
|
||||
dhcpClientApps.Get(0)->TraceConnect ("NewLease", "0", MakeCallback(&DhcpTestCase::LeaseObtained, this));
|
||||
dhcpClientApps.Get(1)->TraceConnect ("NewLease", "1", MakeCallback(&DhcpTestCase::LeaseObtained, this));
|
||||
dhcpClientApps.Get(2)->TraceConnect ("NewLease", "2", MakeCallback(&DhcpTestCase::LeaseObtained, this));
|
||||
|
||||
Simulator::Stop (Seconds (21.0));
|
||||
|
||||
Simulator::Run ();
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (m_leasedAddress[0], Ipv4Address ("172.30.0.10"),
|
||||
m_leasedAddress[0] << " instead of " << "172.30.0.10");
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (m_leasedAddress[1], Ipv4Address ("172.30.0.11"),
|
||||
m_leasedAddress[1] << " instead of " << "172.30.0.11");
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (m_leasedAddress[2], Ipv4Address ("172.30.0.14"),
|
||||
m_leasedAddress[2] << " instead of " << "172.30.0.14");
|
||||
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup dhcp-test
|
||||
* \ingroup tests
|
||||
*
|
||||
* \brief DHCP TestSuite
|
||||
*/
|
||||
class DhcpTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
DhcpTestSuite ();
|
||||
};
|
||||
|
||||
DhcpTestSuite::DhcpTestSuite ()
|
||||
: TestSuite ("dhcp", UNIT)
|
||||
{
|
||||
AddTestCase (new DhcpTestCase, TestCase::QUICK);
|
||||
}
|
||||
|
||||
static DhcpTestSuite dhcpTestSuite; //!< Static variable for test initialization
|
||||
|
||||
@@ -14,9 +14,18 @@ def build(bld):
|
||||
'model/radvd-prefix.cc',
|
||||
'model/radvd.cc',
|
||||
'model/v4ping.cc',
|
||||
'model/dhcp-header.cc',
|
||||
'model/dhcp-server.cc',
|
||||
'model/dhcp-client.cc',
|
||||
'helper/ping6-helper.cc',
|
||||
'helper/radvd-helper.cc',
|
||||
'helper/v4ping-helper.cc',
|
||||
'helper/dhcp-helper.cc',
|
||||
]
|
||||
|
||||
applications_test = bld.create_ns3_module_test_library('internet-apps')
|
||||
applications_test.source = [
|
||||
'test/dhcp-test.cc',
|
||||
]
|
||||
|
||||
headers = bld(features='ns3header')
|
||||
@@ -27,11 +36,17 @@ def build(bld):
|
||||
'model/radvd-interface.h',
|
||||
'model/radvd-prefix.h',
|
||||
'model/v4ping.h',
|
||||
'model/dhcp-header.h',
|
||||
'model/dhcp-server.h',
|
||||
'model/dhcp-client.h',
|
||||
'helper/ping6-helper.h',
|
||||
'helper/v4ping-helper.h',
|
||||
'helper/radvd-helper.h',
|
||||
'helper/dhcp-helper.h',
|
||||
]
|
||||
|
||||
if (bld.env['ENABLE_EXAMPLES']):
|
||||
bld.recurse('examples')
|
||||
|
||||
bld.ns3_python_bindings()
|
||||
|
||||
|
||||
@@ -11,6 +11,89 @@
|
||||
IPv4
|
||||
----
|
||||
|
||||
This chapter describes the |ns3| IPv4 address assignment and basic components tracking.
|
||||
|
||||
IPv4 addresses assignment
|
||||
*************************
|
||||
|
||||
In order to use IPv4 on a network, the first thing to do is assigning IPv4 addresses.
|
||||
|
||||
Any IPv4-enabled |ns3| node will have at least one NetDevice: the :cpp:class:`ns3::LoopbackNetDevice`.
|
||||
The loopback device address is ``127.0.0.1``.
|
||||
All the other NetDevices will have one (or more) IPv4 addresses.
|
||||
|
||||
Note that, as today, |ns3| does not have a NAT module, and it does not follows the rules about
|
||||
filtering private addresses (:rfc:`1918`): 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16.
|
||||
These addresses are routed as any other address. This behaviour could change in the future.
|
||||
|
||||
IPv4 global addresses can be:
|
||||
|
||||
* manually assigned
|
||||
* assigned though DHCP
|
||||
|
||||
|ns3| can use both methods, and it's quite important to understand the implications of both.
|
||||
|
||||
Manually assigned IPv4 adddresses
|
||||
+++++++++++++++++++++++++++++++++
|
||||
|
||||
This is probably the easiest and most used method. As an example:
|
||||
|
||||
::
|
||||
|
||||
Ptr<Node> n0 = CreateObject<Node> ();
|
||||
Ptr<Node> n1 = CreateObject<Node> ();
|
||||
NodeContainer net (n0, n1);
|
||||
CsmaHelper csma;
|
||||
NetDeviceContainer ndc = csma.Install (net);
|
||||
|
||||
NS_LOG_INFO ("Assign IPv4 Addresses.");
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase (Ipv4Address ("192.168.1.0"), NetMask ("/24"));
|
||||
Ipv4InterfaceContainer ic = ipv4.Assign (ndc);
|
||||
|
||||
This method will add two global IPv4 addresses to the nodes.
|
||||
|
||||
Note that the addesses are assigned in sequence. As a consequence, the first Node / NetDevice
|
||||
will have "192.168.1.1", the second "192.168.1.2" and so on.
|
||||
|
||||
It is possible to repeat the above to assign more than one address to a node.
|
||||
However, due to the :cpp:class:`Ipv4AddressHelper` singleton nature, one should first assign all the
|
||||
adddresses of a network, then change the network base (``SetBase``), then do a new assignment.
|
||||
|
||||
Alternatively, it is possible to assign a specific address to a node:
|
||||
|
||||
::
|
||||
|
||||
Ptr<Node> n0 = CreateObject<Node> ();
|
||||
NodeContainer net (n0);
|
||||
CsmaHelper csma;
|
||||
NetDeviceContainer ndc = csma.Install (net);
|
||||
|
||||
NS_LOG_INFO ("Specifically Assign an IPv4 Address.");
|
||||
Ipv4AddressHelper ipv4;
|
||||
Ptr<NetDevice> device = ndc.Get (0);
|
||||
Ptr<Node> node = device->GetNode ();
|
||||
Ptr<Ipv4> ipv4proto = node->GetObject<Ipv4> ();
|
||||
int32_t ifIndex = 0;
|
||||
ifIndex = ipv4proto->GetInterfaceForDevice (device);
|
||||
Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("192.168.1.42"), NetMask ("/24"));
|
||||
ipv4proto->AddAddress (ifIndex, ipv4Addr);
|
||||
|
||||
|
||||
DHCP assigned IPv4 adddresses
|
||||
+++++++++++++++++++++++++++++
|
||||
|
||||
DHCP is available in the internet-apps module. In order to use DHCP you have to have a
|
||||
:cpp:class:`DhcpServer` application in a node (the DHC server node) and a :cpp:class:`DhcpClient` application in
|
||||
each of the nodes. Note that it not necessary that all the nodes in a subnet use DHCP. Some
|
||||
nodes can have static addresses.
|
||||
|
||||
All the DHCP setup is performed though the :cpp:class:`DhcpHelper` class. A complete example is in
|
||||
``src/internet-apps/examples/dhcp-example.cc``.
|
||||
|
||||
Further info about the DHCP functionalities can be found in the ``internet-apps`` model documentation.
|
||||
|
||||
|
||||
Tracing in the IPv4 Stack
|
||||
*************************
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ Note that the global addesses will be derived from the MAC address. As a consequ
|
||||
to have addresses similar to ``2001:db8::200:ff:fe00:1``.
|
||||
|
||||
It is possible to repeat the above to assign more than one global address to a node.
|
||||
However, due to the ``Ipv6AddressHelper`` singleton nature, one should first assign all the
|
||||
However, due to the :cpp:class:`Ipv6AddressHelper` singleton nature, one should first assign all the
|
||||
adddresses of a network, then change the network base (``SetBase``), then do a new assignment.
|
||||
|
||||
Alternatively, it is possible to assign a specific address to a node:
|
||||
|
||||
Reference in New Issue
Block a user