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:
Tom Henderson
2017-07-07 23:21:20 +02:00
parent 17a6187d02
commit 71f73e92b4
17 changed files with 2955 additions and 12 deletions

2
.gitignore vendored
View File

@@ -35,3 +35,5 @@ TAGS
build-dir/
build/
/.cproject
/.project

View File

@@ -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)

View File

@@ -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.

View 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.");
}

View 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'

View 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

View 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 */

View 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

View 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 */

View 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

View 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 */

View 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

View 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 */

View 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

View File

@@ -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()

View File

@@ -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
*************************

View File

@@ -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: