A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
dhcp-client.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011 UPB
3 * Copyright (c) 2017 NITK Surathkal
4 *
5 * SPDX-License-Identifier: GPL-2.0-only
6 *
7 * Author: Radu Lupu <rlupu@elcom.pub.ro>
8 * Ankit Deepak <adadeepak8@gmail.com>
9 * Deepti Rajagopal <deeptir96@gmail.com>
10 *
11 *
12 */
13
14#include "dhcp-client.h"
15
16#include "dhcp-header.h"
17
18#include "ns3/ipv4-routing-table-entry.h"
19#include "ns3/ipv4-static-routing-helper.h"
20#include "ns3/ipv4.h"
21#include "ns3/log.h"
22#include "ns3/pointer.h"
23#include "ns3/random-variable-stream.h"
24#include "ns3/string.h"
25
26namespace ns3
27{
28
29NS_LOG_COMPONENT_DEFINE("DhcpClient");
31
32TypeId
34{
35 static TypeId tid =
36 TypeId("ns3::DhcpClient")
38 .AddConstructor<DhcpClient>()
39 .SetGroupName("Internet-Apps")
40 .AddAttribute("RTRS",
41 "Time for retransmission of Discover message",
45 .AddAttribute("Collect",
46 "Time for which offer collection starts",
50 .AddAttribute("ReRequest",
51 "Time after which request will be resent to next server",
52 TimeValue(Seconds(10)),
55 .AddAttribute("Transactions",
56 "The possible value of transaction numbers",
57 StringValue("ns3::UniformRandomVariable[Min=0.0|Max=1000000.0]"),
60 .AddTraceSource("NewLease",
61 "Get a NewLease",
63 "ns3::Ipv4Address::TracedCallback")
64 .AddTraceSource("ExpireLease",
65 "A lease expires",
67 "ns3::Ipv4Address::TracedCallback");
68 return tid;
69}
70
85
87{
88 NS_LOG_FUNCTION(this << netDevice);
89 m_device = netDevice;
91 m_socket = nullptr;
99 m_firstBoot = true;
100}
101
106
112
113void
115{
116 m_device = netDevice;
117}
118
121{
122 return m_server;
123}
124
125void
127{
128 NS_LOG_FUNCTION(this);
129
130 m_device = nullptr;
131
132 // Stop all the timers
140
142}
143
144int64_t
146{
147 NS_LOG_FUNCTION(this << stream);
148 auto currentStream = stream;
149 m_ran->SetStream(currentStream++);
150 currentStream += Application::AssignStreams(currentStream);
151 return (currentStream - stream);
152}
153
154void
156{
157 NS_LOG_FUNCTION(this);
158
159 m_remoteAddress = Ipv4Address("255.255.255.255");
160 m_myAddress = Ipv4Address("0.0.0.0");
161 m_gateway = Ipv4Address("0.0.0.0");
162 Ptr<Ipv4> ipv4 = GetNode()->GetObject<Ipv4>();
163 uint32_t ifIndex = ipv4->GetInterfaceForDevice(m_device);
164
165 // We need to cleanup the type from the stored chaddr, or later we'll fail to compare it.
166 // Moreover, the length is always 16, because chaddr is 16 bytes.
167 Address myAddress = m_device->GetAddress();
168 NS_LOG_INFO("My address is " << myAddress);
169 uint8_t addr[Address::MAX_SIZE];
170 std::memset(addr, 0, Address::MAX_SIZE);
171 uint32_t len = myAddress.CopyTo(addr);
172 NS_ASSERT_MSG(len <= 16, "DHCP client can not handle a chaddr larger than 16 bytes");
173 m_chaddr.CopyFrom(addr, 16);
174 NS_LOG_INFO("My m_chaddr is " << m_chaddr);
175
176 bool found = false;
177 for (uint32_t i = 0; i < ipv4->GetNAddresses(ifIndex); i++)
178 {
179 if (ipv4->GetAddress(ifIndex, i).GetLocal() == m_myAddress)
180 {
181 found = true;
182 }
183 }
184 if (!found)
185 {
186 ipv4->AddAddress(ifIndex, Ipv4InterfaceAddress(Ipv4Address("0.0.0.0"), Ipv4Mask("/0")));
187 }
188 if (!m_socket)
189 {
190 TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory");
195 m_socket->Bind(local);
196 }
198
199 if (m_firstBoot)
200 {
201 m_device->AddLinkChangeCallback(MakeCallback(&DhcpClient::LinkStateHandler, this));
202 m_firstBoot = false;
203 }
204 Boot();
205}
206
207void
209{
210 NS_LOG_FUNCTION(this);
211
212 // Stop all the timers
220
221 Ptr<Ipv4> ipv4 = GetNode()->GetObject<Ipv4>();
222
223 int32_t ifIndex = ipv4->GetInterfaceForDevice(m_device);
224 for (uint32_t i = 0; i < ipv4->GetNAddresses(ifIndex); i++)
225 {
226 if (ipv4->GetAddress(ifIndex, i).GetLocal() == m_myAddress)
227 {
228 ipv4->RemoveAddress(ifIndex, i);
229 break;
230 }
231 }
232
234 m_socket->Close();
235}
236
237void
239{
240 NS_LOG_FUNCTION(this);
241
242 if (m_device->IsLinkUp())
243 {
244 NS_LOG_INFO("Link up at " << Simulator::Now().As(Time::S));
247 }
248 else
249 {
250 NS_LOG_INFO("Link down at " << Simulator::Now().As(Time::S)); // reinitialization
251
252 // Stop all the timers
260
262 MakeNullCallback<void, Ptr<Socket>>()); // stop receiving on this socket !!!
263
264 Ptr<Ipv4> ipv4MN = GetNode()->GetObject<Ipv4>();
265 int32_t ifIndex = ipv4MN->GetInterfaceForDevice(m_device);
266
267 for (uint32_t i = 0; i < ipv4MN->GetNAddresses(ifIndex); i++)
268 {
269 if (ipv4MN->GetAddress(ifIndex, i).GetLocal() == m_myAddress)
270 {
271 ipv4MN->RemoveAddress(ifIndex, i);
272 break;
273 }
274 }
275
276 Ipv4StaticRoutingHelper ipv4RoutingHelper;
277 Ptr<Ipv4StaticRouting> staticRouting = ipv4RoutingHelper.GetStaticRouting(ipv4MN);
278 uint32_t i;
279 for (i = 0; i < staticRouting->GetNRoutes(); i++)
280 {
281 if (staticRouting->GetRoute(i).GetGateway() == m_gateway)
282 {
283 staticRouting->RemoveRoute(i);
284 break;
285 }
286 }
287
288 m_state = 0;
289 m_myAddress = Ipv4Address("0.0.0.0");
290 m_gateway = Ipv4Address("0.0.0.0");
291 }
292}
293
294void
296{
297 NS_LOG_FUNCTION(this << socket);
298
299 Address from;
300 Ptr<Packet> packet = m_socket->RecvFrom(from);
301 DhcpHeader header;
302 if (packet->RemoveHeader(header) == 0)
303 {
304 return;
305 }
306 if (header.GetChaddr() != m_chaddr)
307 {
308 return;
309 }
310 if (m_state == WAIT_OFFER && header.GetType() == DhcpHeader::DHCPOFFER)
311 {
312 OfferHandler(header);
313 }
314 if (m_state == WAIT_ACK && header.GetType() == DhcpHeader::DHCPACK)
315 {
317 AcceptAck(header, from);
318 }
319 if (m_state == WAIT_ACK && header.GetType() == DhcpHeader::DHCPNACK)
320 {
322 Boot();
323 }
324}
325
326void
328{
329 NS_LOG_FUNCTION(this);
330
331 DhcpHeader header;
332 Ptr<Packet> packet;
333 packet = Create<Packet>();
334 header.ResetOpt();
336 header.SetTran(m_tran);
338 header.SetTime();
339 header.SetChaddr(m_chaddr);
340 packet->AddHeader(header);
341
342 if ((m_socket->SendTo(packet,
343 0,
344 InetSocketAddress(Ipv4Address("255.255.255.255"), DHCP_PEER_PORT))) >= 0)
345 {
346 NS_LOG_INFO("DHCP DISCOVER sent");
347 }
348 else
349 {
350 NS_LOG_INFO("Error while sending DHCP DISCOVER to " << m_remoteAddress);
351 }
353 m_offered = false;
355}
356
357void
359{
360 NS_LOG_FUNCTION(this << header);
361
362 m_offerList.push_back(header);
363 if (!m_offered)
364 {
366 m_offered = true;
368 }
369}
370
371void
373{
374 NS_LOG_FUNCTION(this);
375
376 if (m_offerList.empty())
377 {
378 Boot();
379 return;
380 }
381
382 DhcpHeader header = m_offerList.front();
383 m_offerList.pop_front();
384 m_lease = Time(Seconds(header.GetLease()));
385 m_renew = Time(Seconds(header.GetRenew()));
386 m_rebind = Time(Seconds(header.GetRebind()));
387 m_offeredAddress = header.GetYiaddr();
388 m_myMask = Ipv4Mask(header.GetMask());
389 m_server = header.GetDhcps();
390 m_gateway = header.GetRouter();
391 m_offerList.clear();
392 m_offered = false;
393 Request();
394}
395
396void
398{
399 NS_LOG_FUNCTION(this);
400
401 DhcpHeader header;
402 Ptr<Packet> packet;
403 if (m_state != REFRESH_LEASE)
404 {
405 packet = Create<Packet>();
406 header.ResetOpt();
408 header.SetTime();
409 header.SetTran(m_tran);
410 header.SetReq(m_offeredAddress);
411 header.SetChaddr(m_chaddr);
412 packet->AddHeader(header);
413 m_socket->SendTo(packet,
414 0,
415 InetSocketAddress(Ipv4Address("255.255.255.255"), DHCP_PEER_PORT));
418 }
419 else
420 {
421 uint32_t addr = m_myAddress.Get();
422 packet = Create<Packet>((uint8_t*)&addr, sizeof(addr));
423 header.ResetOpt();
425 header.SetTran(m_tran);
426 header.SetTime();
428 header.SetReq(m_myAddress);
430 header.SetChaddr(m_chaddr);
431 packet->AddHeader(header);
433 {
434 NS_LOG_INFO("DHCP REQUEST sent");
435 }
436 else
437 {
438 NS_LOG_INFO("Error while sending DHCP REQ to " << m_remoteAddress);
439 }
441 }
442}
443
444void
446{
447 NS_LOG_FUNCTION(this << header << from);
448
452
453 NS_LOG_INFO("DHCP ACK received");
454 Ptr<Ipv4> ipv4 = GetNode()->GetObject<Ipv4>();
455 int32_t ifIndex = ipv4->GetInterfaceForDevice(m_device);
456
458 {
459 for (uint32_t i = 0; i < ipv4->GetNAddresses(ifIndex); i++)
460 {
461 if (ipv4->GetAddress(ifIndex, i).GetLocal() == m_myAddress)
462 {
463 NS_LOG_LOGIC("Got a new address (" << m_offeredAddress
464 << "), removing old one: " << m_myAddress);
465 ipv4->RemoveAddress(ifIndex, i);
466 break;
467 }
468 }
469
470 ipv4->AddAddress(ifIndex, Ipv4InterfaceAddress(m_offeredAddress, m_myMask));
471 ipv4->SetUp(ifIndex);
472 }
473
474 InetSocketAddress remote =
476 m_socket->Connect(remote);
478 {
480 if (m_myAddress != Ipv4Address("0.0.0.0"))
481 {
483 }
484 }
486 Ipv4StaticRoutingHelper ipv4RoutingHelper;
487 Ptr<Ipv4StaticRouting> staticRouting = ipv4RoutingHelper.GetStaticRouting(ipv4);
488 if (m_gateway == Ipv4Address("0.0.0.0"))
489 {
491 }
492
493 staticRouting->SetDefaultRoute(m_gateway, ifIndex, 0);
494
496 NS_LOG_INFO("Current DHCP Server is " << m_remoteAddress);
497
498 m_offerList.clear();
503}
504
505void
507{
508 NS_LOG_FUNCTION(this);
509
514
515 Ptr<Ipv4> ipv4MN = GetNode()->GetObject<Ipv4>();
516 int32_t ifIndex = ipv4MN->GetInterfaceForDevice(m_device);
517
518 for (uint32_t i = 0; i < ipv4MN->GetNAddresses(ifIndex); i++)
519 {
520 if (ipv4MN->GetAddress(ifIndex, i).GetLocal() == m_myAddress)
521 {
522 ipv4MN->RemoveAddress(ifIndex, i);
523 break;
524 }
525 }
527 Ipv4StaticRoutingHelper ipv4RoutingHelper;
528 Ptr<Ipv4StaticRouting> staticRouting = ipv4RoutingHelper.GetStaticRouting(ipv4MN);
529 uint32_t i;
530 for (i = 0; i < staticRouting->GetNRoutes(); i++)
531 {
532 if (staticRouting->GetRoute(i).GetGateway() == m_gateway)
533 {
534 staticRouting->RemoveRoute(i);
535 break;
536 }
537 }
539}
540
541} // Namespace ns3
a polymophic address class
Definition address.h:90
uint32_t CopyFrom(const uint8_t *buffer, uint8_t len)
Definition address.cc:95
static constexpr uint32_t MAX_SIZE
The maximum size of a byte buffer which can be stored in an Address instance.
Definition address.h:96
uint32_t CopyTo(uint8_t buffer[MAX_SIZE]) const
Copy the address bytes into a buffer.
Definition address.cc:75
The base class for all ns3 applications.
Definition application.h:51
void DoDispose() override
Destructor implementation.
virtual int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this Application object.
Ptr< Node > GetNode() const
EventId m_requestEvent
Address refresh event.
Ipv4Address m_gateway
Address of the gateway.
static TypeId GetTypeId()
Get the type ID.
Ipv4Mask m_myMask
Mask of the address assigned.
Time m_rebind
Store the rebind time of address.
void SetDhcpClientNetDevice(Ptr< NetDevice > netDevice)
Set the NetDevice DHCP should work on.
void LinkStateHandler()
Handles changes in LinkState.
void DoDispose() override
Destructor implementation.
uint32_t m_tran
Stores the current transaction number to be used.
void RemoveAndStart()
Remove the current DHCP information and restart the process.
Ptr< Socket > m_socket
Socket for remote communication.
bool m_firstBoot
First boot (used to add the link state change callback)
Time m_collect
Time for which client should collect offers.
Address m_chaddr
chaddr of the interface (stored as an Address for convenience).
@ WAIT_OFFER
State of a client that waits for the offer.
Definition dhcp-client.h:84
@ WAIT_ACK
State of a client that waits for acknowledgment.
Definition dhcp-client.h:86
@ REFRESH_LEASE
State of a client that needs to refresh the lease.
Definition dhcp-client.h:85
void StopApplication() override
Application specific shutdown code.
Ptr< NetDevice > m_device
NetDevice pointer.
EventId m_timeout
The timeout period.
Ptr< RandomVariableStream > m_ran
Uniform random variable for transaction ID.
EventId m_rebindEvent
Message rebind event.
static const int DHCP_PEER_PORT
DHCP server port.
Definition dhcp-client.h:89
std::list< DhcpHeader > m_offerList
Stores all the offers given to the client.
Ptr< NetDevice > GetDhcpClientNetDevice()
Get the the NetDevice DHCP should work on.
Ipv4Address m_server
Address of the DHCP server.
int64_t AssignStreams(int64_t stream) override
Assign a fixed random variable stream number to the random variables used by this Application object.
EventId m_nextOfferEvent
Message next offer event.
void StartApplication() override
Application specific startup code.
void Boot()
Sends DHCP DISCOVER and changes the client state to WAIT_OFFER.
bool m_offered
Specify if the client has got any offer.
void OfferHandler(DhcpHeader header)
Stores DHCP offers in m_offerList.
void Request()
Sends the DHCP REQUEST message and changes the client state to WAIT_ACK.
TracedCallback< const Ipv4Address & > m_expiry
Trace of lease expire.
TracedCallback< const Ipv4Address & > m_newLease
Trace of new lease.
Ipv4Address GetDhcpServer()
Get the IPv4Address of current DHCP server.
uint8_t m_state
State of the DHCP client.
EventId m_discoverEvent
Message retransmission event.
EventId m_refreshEvent
Message refresh event.
Ipv4Address m_myAddress
Address assigned to the client.
Time m_rtrs
Defining the time for retransmission.
~DhcpClient() override
void Select()
Selects an OFFER from m_offerList.
Time m_nextoffer
Time to try the next offer (if request gets no reply)
Ipv4Address m_remoteAddress
Initially set to 255.255.255.255 to start DHCP.
void NetHandler(Ptr< Socket > socket)
Handles incoming packets from the network.
void AcceptAck(DhcpHeader header, Address from)
Receives the DHCP ACK and configures IP address of the client.
Ipv4Address m_offeredAddress
Address offered to the client.
Time m_renew
Store the renew time of address.
EventId m_collectEvent
Offer collection event.
Time m_lease
Store the lease time of address.
BOOTP header with DHCP messages.
Definition dhcp-header.h:73
uint32_t GetLease() const
Return the lease time of the IPv4Address.
void SetTime()
Set the time when message is sent.
void ResetOpt()
Reset the BOOTP options.
Ipv4Address GetRouter() const
Return the Ipv4Address of gateway to be used.
void SetType(uint8_t type)
Set the type of BOOTP and DHCP messages.
@ DHCPACK
Code for DHCP ACK.
@ DHCPOFFER
Code for DHCP Offer.
@ DHCPDISCOVER
Code for DHCP Discover.
@ DHCPREQ
Code for DHCP Request.
@ DHCPNACK
Code for DHCP NACK.
void SetTran(uint32_t tran)
Set the transaction ID.
Address GetChaddr()
Get the Address of the client.
Ipv4Address GetDhcps() const
Get the information about the DHCP server.
uint32_t GetMask() const
Return the mask of the network.
uint8_t GetType() const
Return the type of DHCP message.
void SetReq(Ipv4Address addr)
Set the Ipv4Address requested by the client.
Ipv4Address GetYiaddr() const
Get the IPv4Address of the client.
uint32_t GetRebind() const
Return the Rebind time of the address.
void SetChaddr(Address addr)
Set the Address of the device.
uint32_t GetRenew() const
Return the Renewal time of the address.
An identifier for simulation events.
Definition event-id.h:45
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition event-id.cc:44
an Inet address class
Ipv4Address GetIpv4() const
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
Ipv4 addresses are stored in host order in this class.
uint32_t Get() const
Get the host-order 32-bit IP address.
static Ipv4Address GetAny()
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition ipv4.h:69
a class to store IPv4 address information on an interface
a class to represent an Ipv4 address mask
Helper class that adds ns3::Ipv4StaticRouting objects.
Ptr< Ipv4StaticRouting > GetStaticRouting(Ptr< Ipv4 > ipv4) const
Try and find the static routing protocol as either the main routing protocol or in the list of routin...
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:511
Smart pointer class similar to boost::intrusive_ptr.
virtual double GetValue()=0
Get the next random value drawn from the distribution.
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)=0
Read a single packet from the socket and retrieve the sender address.
virtual bool SetAllowBroadcast(bool allowBroadcast)=0
Configure whether broadcast datagram transmissions are allowed.
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
Definition socket.cc:316
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition socket.cc:117
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
Definition socket.cc:61
virtual int Close()=0
Close a socket.
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)=0
Send data to a specified peer.
Hold variables of type string.
Definition string.h:45
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
@ S
second
Definition nstime.h:105
AttributeValue implementation for Time.
Definition nstime.h:1395
a unique identifier for an interface.
Definition type-id.h:48
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition type-id.cc:872
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition pointer.h:248
Ptr< AttributeChecker > MakePointerChecker()
Create a PointerChecker for a type.
Definition pointer.h:269
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition nstime.h:1396
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1416
Callback< R, Args... > MakeNullCallback()
Definition callback.h:727
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:684