14#include "ns3/address-utils.h"
15#include "ns3/icmpv6-l4-protocol.h"
16#include "ns3/ipv6-interface.h"
17#include "ns3/ipv6-l3-protocol.h"
18#include "ns3/ipv6-packet-info-tag.h"
21#include "ns3/loopback-net-device.h"
22#include "ns3/simulator.h"
23#include "ns3/socket.h"
38 .AddConstructor<Dhcp6Server>()
39 .SetGroupName(
"InternetApps")
40 .AddAttribute(
"RenewTime",
41 "Time after which client should renew. 1000 seconds by default in Linux. "
42 "This is equivalent to REN_MAX_RT (RFC 8415, Section 7.6).",
46 .AddAttribute(
"RebindTime",
47 "Time after which client should rebind. "
48 "2000 seconds by default in Linux. "
49 "This is equivalent to REB_MAX_RT (RFC 8415, Section 7.6).",
53 .AddAttribute(
"PreferredLifetime",
54 "The preferred lifetime of the leased address. "
55 "3000 seconds by default in Linux.",
59 .AddAttribute(
"ValidLifetime",
60 "Time after which client should release the address. "
61 "4000 seconds by default in Linux.",
86 itr.m_leasedAddresses.clear();
87 itr.m_expiredAddresses.clear();
88 itr.m_declinedAddresses.clear();
115 std::map<Options::OptionType, bool> headerOptions = header.
GetOptionList();
121 for (
const auto& itr : iaOpt)
126 NS_LOG_DEBUG(
"DHCPv6 server: Client registering IAID " << iaid);
153 std::vector<uint32_t> requestedIa(ianaOptionsList.size());
154 for (std::size_t i = 0; i < ianaOptionsList.size(); i++)
156 requestedIa[i] = ianaOptionsList[i].GetIaid();
173 uint8_t offeredAddrBuf[16];
175 bool foundAddress =
false;
176 if (!subnet.m_expiredAddresses.empty())
180 for (
auto itr = subnet.m_expiredAddresses.begin();
181 itr != subnet.m_expiredAddresses.end();)
183 if (itr->second.first == clientDuid)
185 nextAddress = itr->second.second;
186 nextAddress.
GetBytes(offeredAddrBuf);
187 itr = subnet.m_expiredAddresses.erase(itr);
199 if (!foundAddress && subnet.m_expiredAddresses.size() > 30)
201 auto firstExpiredAddress = subnet.m_expiredAddresses.begin();
202 nextAddress = firstExpiredAddress->second.second;
203 nextAddress.
GetBytes(offeredAddrBuf);
204 subnet.m_expiredAddresses.erase(firstExpiredAddress);
212 uint8_t minAddrBuf[16];
216 uint8_t lastLeasedAddrBuf[16];
218 if (!subnet.m_leasedAddresses.empty())
221 subnet.m_maxOfferedAddress.GetBytes(lastLeasedAddrBuf);
222 memcpy(offeredAddrBuf, lastLeasedAddrBuf, 16);
225 bool addedOne =
false;
226 for (uint8_t i = 15; !addedOne && i >= 0; i--)
228 for (
int j = 0; j < 8; j++)
230 uint8_t bit = (offeredAddrBuf[i] & (1 << j)) >> j;
233 offeredAddrBuf[i] = offeredAddrBuf[i] | (1 << j);
237 offeredAddrBuf[i] = offeredAddrBuf[i] & ~(1 << j);
243 memcpy(offeredAddrBuf, minAddrBuf, 16);
247 subnet.m_maxOfferedAddress = offer;
253 subnet.m_leasedAddresses.insert(
261 for (
const auto& iaid : requestedIa)
272 std::map<Options::OptionType, bool> headerOptions = header.
GetOptionList();
275 std::vector<Options::OptionType> requestedOptions =
280 packet->AddHeader(advertiseHeader);
284 int32_t ifIndex = ipv6->GetInterfaceForDevice(iDev);
288 if (sendSocket->SendTo(packet, 0, client) >= 0)
294 NS_LOG_INFO(
"Error while sending DHCPv6 Advertise.");
322 for (
auto& iaOpt : ianaOptionsList)
326 std::vector<IaAddressOption> iaAddrOptList = iaOpt.m_iaAddressOption;
327 for (
auto& addrItr : iaAddrOptList)
329 Ipv6Address requestedAddr = addrItr.GetIaAddress();
340 if (subnet.m_declinedAddresses.find(requestedAddr) !=
341 subnet.m_declinedAddresses.end())
343 NS_LOG_INFO(
"Requested address" << requestedAddr <<
"is declined.");
348 if (prefix.
IsMatch(requestedAddr, pool))
352 uint8_t requestedBuf[16];
355 requestedAddr.
GetBytes(requestedBuf);
357 if (memcmp(requestedBuf, minBuf, 16) < 0 ||
358 memcmp(requestedBuf, maxBuf, 16) > 0)
360 NS_LOG_INFO(
"Requested address is not in the range of the subnet.");
365 replyHeader.
AddIanaOption(iaOpt.GetIaid(), iaOpt.GetT1(), iaOpt.GetT2());
371 NS_LOG_DEBUG(
"Adding address " << requestedAddr <<
" to lease");
374 auto range = subnet.m_leasedAddresses.equal_range(clientDuid);
377 std::multimap<Duid, std::pair<Ipv6Address, Time>> updatedLifetimes;
378 for (
auto it = range.first; it != range.second; it++)
381 std::pair<Ipv6Address, Time> clientLeaseTime = {
386 updatedLifetimes.insert({clientDuid, clientLeaseTime});
391 subnet.m_leasedAddresses.erase(range.first->first);
394 for (
auto& itr : updatedLifetimes)
396 subnet.m_leasedAddresses.insert({itr.first, itr.second});
404 std::map<Options::OptionType, bool> headerOptions = header.
GetOptionList();
409 std::vector<Options::OptionType> requestedOptions =
414 packet->AddHeader(replyHeader);
418 int32_t ifIndex = ipv6->GetInterfaceForDevice(iDev);
422 if (sendSocket->SendTo(packet, 0, client) >= 0)
455 for (
auto& iaOpt : ianaOptionsList)
457 std::vector<IaAddressOption> iaAddrOptList = iaOpt.m_iaAddressOption;
460 replyHeader.
AddIanaOption(iaOpt.GetIaid(), iaOpt.GetT1(), iaOpt.GetT2());
462 for (
const auto& addrItr : iaAddrOptList)
476 if (prefix.
IsMatch(clientLease, pool))
479 auto range = subnet.m_leasedAddresses.equal_range(clientDuid);
480 for (
auto itr = range.first; itr != range.second; itr++)
483 if (itr->second.first == clientLease)
485 NS_LOG_DEBUG(
"Renewing address: " << itr->second.first);
487 std::pair<Ipv6Address, Time> clientLeaseTime = {
492 subnet.m_leasedAddresses.erase(itr);
495 subnet.m_leasedAddresses.insert({clientDuid, clientLeaseTime});
510 std::map<Options::OptionType, bool> headerOptions = header.
GetOptionList();
513 std::vector<Options::OptionType> requestedOptions =
518 packet->AddHeader(replyHeader);
522 int32_t ifIndex = ipv6->GetInterfaceForDevice(iDev);
526 if (sendSocket->SendTo(packet, 0, client) >= 0)
562 for (
const auto& iaOpt : ianaOptionsList)
564 std::vector<IaAddressOption> iaAddrOptList = iaOpt.m_iaAddressOption;
566 for (
const auto& addrItr : iaAddrOptList)
576 for (
auto itr = subnet.m_leasedAddresses.begin();
577 itr != subnet.m_leasedAddresses.end();)
580 if (leaseAddr == address)
582 itr = subnet.m_leasedAddresses.erase(itr);
583 subnet.m_declinedAddresses[address] = clientDuid;
597 for (
auto itr = subnet.m_leasedAddresses.begin();
598 itr != subnet.m_leasedAddresses.end();)
600 Duid duid = itr->first;
602 Time expiredTime = itr->second.second;
603 if (leaseAddr == address)
605 itr = subnet.m_leasedAddresses.erase(itr);
606 std::pair<Duid, Ipv6Address> expiredLease = {duid, leaseAddr};
607 subnet.m_expiredAddresses.insert({expiredTime, expiredLease});
617 packet->AddHeader(replyHeader);
621 int32_t ifIndex = ipv6->GetInterfaceForDevice(iDev);
625 if (sendSocket->SendTo(packet, 0, client) >= 0)
638 for (
auto itr = netDevices.
Begin(); itr != netDevices.
End(); itr++)
641 int32_t ifIndex = ipv6->GetInterfaceForDevice(*itr);
660 "No incoming interface on DHCPv6 message.");
665 if (packet->RemoveHeader(header) == 0)
701 NS_LOG_FUNCTION(
this << addressPool << prefix << minAddress << maxAddress);
703 NS_LOG_DEBUG(
"DHCPv6 server: Adding subnet " << addressPool <<
" to lease information.");
704 LeaseInfo newSubnet(addressPool, prefix, minAddress, maxAddress);
721 if (ifIndex == recvInterface)
724 ipv6l3->GetInterface(ifIndex)->GetLinkLocalAddress().GetAddress();
730 socket->BindToNetDevice(device);
731 socket->SetRecvPktInfo(
true);
746 NS_LOG_INFO(
"DHCPv6 daemon is not meant to be started repeatedly.");
769 NS_LOG_DEBUG(
"DHCPv6 server: Node " << node->GetId() <<
" listening on interface "
773 "Dhcp6Server::StartApplication: device is not connected to IPv6.");
796 for (
auto itr = subnet.m_leasedAddresses.begin(); itr != subnet.m_leasedAddresses.end();)
798 Duid duid = itr->first;
800 Time leaseTime = itr->second.second;
804 NS_LOG_DEBUG(
"DHCPv6 server: Removing expired lease for " << address);
805 std::pair<Duid, Ipv6Address> expiredLease = {duid, address};
806 subnet.m_expiredAddresses.insert({leaseTime, expiredLease});
807 itr = subnet.m_leasedAddresses.erase(itr);
a polymophic address class
The base class for all ns3 applications.
void DoDispose() override
Destructor implementation.
Ptr< Node > GetNode() const
void SendAdvertise(Ptr< NetDevice > iDev, Dhcp6Header header, Inet6SocketAddress client)
Sends DHCPv6 Advertise after receiving DHCPv6 Solicit.
std::unordered_map< uint32_t, Ptr< Socket > > m_sendSockets
Map of NetDevice - Corresponding socket used to send packets.
void DoDispose() override
Destructor implementation.
void SendReply(Ptr< NetDevice > iDev, Dhcp6Header header, Inet6SocketAddress client)
Sends Reply after receiving Request.
void StartApplication() override
Application specific startup code.
void AddSubnet(Ipv6Address pool, Ipv6Prefix prefix, Ipv6Address minAddress, Ipv6Address maxAddress)
Add a managed address pool.
std::multimap< Duid, std::pair< Options::OptionType, uint32_t > > m_iaBindings
Store IA bindings. Map of DUID + IA Type / IAID.
Duid m_serverDuid
Server DUID.
EventId m_leaseCleanupEvent
Event ID for lease cleanup.
void NetHandler(Ptr< Socket > socket)
Handles incoming packets from the network.
static TypeId GetTypeId()
Get the type ID.
Dhcp6Server()
Default constructor.
Ptr< Socket > m_recvSocket
Socket bound to port 547.
Time m_validLifetime
Default valid lifetime.
Time m_prefLifetime
Default preferred lifetime for an address.
Time m_renew
The default renew timer.
std::vector< LeaseInfo > m_subnets
List of managed subnets.
void SetDhcp6ServerNetDevice(NetDeviceContainer netDevices)
Set the list of net devices that the DHCPv6 server will use.
void CleanLeases()
Clean up stale lease info.
void ProcessSolicit(Ptr< NetDevice > iDev, Dhcp6Header header, Inet6SocketAddress client)
Sends DHCPv6 Advertise after receiving DHCPv6 Solicit.
void StopApplication() override
Application specific shutdown code.
Time m_leaseCleanup
Lease cleanup time.
void ReceiveMflag(uint32_t recvInterface)
Callback for when an M flag is received.
void UpdateBindings(Ptr< NetDevice > iDev, Dhcp6Header header, Inet6SocketAddress client)
Sends Reply after receiving Request.
void RenewRebindLeases(Ptr< NetDevice > iDev, Dhcp6Header header, Inet6SocketAddress client)
Sends Reply after receiving Request.
Time m_rebind
The default rebind timer.
Implements the unique identifier for DHCPv6.
void Initialize(Ptr< Node > node)
Initialize the DUID for a client or server.
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
static uint16_t GetStaticProtocolNumber()
Get ICMPv6 protocol number.
Duid GetDuid() const
Get the DUID object.
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
Describes an IPv6 address.
static Ipv6Address GetAllNodesMulticast()
Get the "all nodes multicast" address.
void GetBytes(uint8_t buf[16]) const
Get the bytes corresponding to the address.
Access to the IPv6 forwarding table, interfaces, and configuration.
IPv6 layer implementation.
This class implements a tag that carries socket ancillary data to the socket interface.
uint32_t GetRecvIf() const
Get the tag's receiving interface.
Describes an IPv6 prefix.
bool IsMatch(Ipv6Address a, Ipv6Address b) const
If the Address match the type.
Includes information about available subnets and corresponding leases.
Ipv6Address GetMinAddress() const
Get the minimum address in the pool.
uint32_t GetNumAddresses() const
Get the number of addresses leased.
Ipv6Address m_maxAddress
Maximum address in the pool.
Ipv6Prefix GetPrefix() const
Get the prefix of the address pool.
Ipv6Prefix m_prefix
Prefix of the address pool.
Ipv6Address GetMaxAddress() const
Get the maximum address in the pool.
Ipv6Address m_addressPool
Address pool.
Ipv6Address GetAddressPool() const
Get the address pool.
Ipv6Address m_minAddress
Minimum address in the pool.
uint32_t m_numAddresses
Number of addresses leased.
LeaseInfo(Ipv6Address addressPool, Ipv6Prefix prefix, Ipv6Address minAddress, Ipv6Address maxAddress)
Constructor.
holds a vector of ns3::NetDevice pointers
Iterator Begin() const
Get an iterator which refers to the first NetDevice in the container.
Iterator End() const
Get an iterator which indicates past-the-last NetDevice in the container.
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Smart pointer class similar to boost::intrusive_ptr.
std::vector< OptionType > GetRequestedOptions() const
Get the option values.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static Time Now()
Return the current simulation virtual time.
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.
void SetRecvPktInfo(bool flag)
Enable/Disable receive packet information to socket.
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
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...
virtual int Close()=0
Close a socket.
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
Simulation virtual time values and global simulation resolution.
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
AttributeValue implementation for Time.
a unique identifier for an interface.
static TypeId LookupByName(std::string name)
Get a TypeId by name.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Callback< R, Args... > MakeNullCallback()
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#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.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Time Seconds(double value)
Construct a Time in the indicated unit.
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...
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.