A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
dhcp6-header.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024 NITK Surathkal
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Kavya Bhat <kavyabhat@gmail.com>
7 *
8 */
9
10#include "dhcp6-header.h"
11
12#include "dhcp6-duid.h"
13
14#include "ns3/address-utils.h"
15#include "ns3/assert.h"
16#include "ns3/log.h"
17#include "ns3/simulator.h"
18
19#include <bitset>
20
21namespace ns3
22{
23
24NS_LOG_COMPONENT_DEFINE("Dhcp6Header");
25
27 : m_len(4),
28 m_msgType(MessageType::INIT),
29 m_transactId(0)
30{
31 m_solMaxRt = 7200;
32}
33
36{
37 return m_msgType;
38}
39
40void
42{
43 NS_LOG_FUNCTION(this << (uint8_t)msgType);
44 m_msgType = msgType;
45}
46
49{
50 return m_transactId;
51}
52
53void
55{
56 NS_LOG_FUNCTION(this << transactId);
57 m_transactId = transactId;
58}
59
60void
65
66void
68{
69 m_len = 4;
70 m_options.clear();
71}
72
75{
76 static TypeId tid = TypeId("ns3::Dhcp6Header")
78 .SetGroupName("Internet-Apps")
79 .AddConstructor<Dhcp6Header>();
80 return tid;
81}
82
85{
86 return GetTypeId();
87}
88
94
100
106
107std::vector<IaOptions>
112
113void
115{
116 // Set the code, length, value.
119 m_elapsedTime.SetOptionValue(timestamp);
120
121 // Increase the total length by 6 bytes.
123
124 // Set the option flag to true.
126}
127
128void
133
134void
139
140void
142 Options::OptionType optionType,
143 Duid duid)
144{
145 // DUID type (2 bytes) + hw type (2 bytes) + Link-layer Address (variable)
146 uint16_t duidLength = 2 + 2 + duid.GetLength();
147
148 // Set the option code, length, hardware type, link layer address.
149 identifier.SetOptionCode(optionType);
150 identifier.SetOptionLength(duidLength);
151 identifier.SetDuid(duid);
152
153 // Increase the total length by (4 + duidLength) bytes.
154 AddMessageLength(4 + duidLength);
155
156 // Set the option flag to true.
157 m_options[optionType] = true;
158}
159
165
166void
168{
169 // Check if this is the first option request.
171 {
173 }
174
175 // Set the option code, length, and add the requested option.
179
180 // Increase the total length by 2 bytes.
182
183 // Set the option flag to true.
185}
186
187void
188Dhcp6Header::HandleOptionRequest(std::vector<Options::OptionType> requestedOptions)
189{
190 // Currently, only Options::OptionType::OPTION_SOL_MAX_RT is supported.
191 for (auto itr : requestedOptions)
192 {
193 switch (itr)
194 {
196 AddSolMaxRt();
197 break;
198 default:
199 NS_LOG_WARN("Requested Option not supported.");
200 }
201 }
202}
203
204void
206{
207 // Increase the total message length.
208 // 4 bytes - for option code + option length.
209 // 4 bytes - for the option value.
210 AddMessageLength(4 + 4);
211
213}
214
215void
220
221void
226
227void
229{
230 // Create a new identity association.
231 IaOptions newIa;
232 newIa.SetOptionCode(optionType);
233
234 // Minimum option length of an IA is 12 bytes.
235 uint16_t optionLength = 12;
236
237 newIa.SetOptionLength(optionLength);
238 newIa.SetIaid(iaid);
239 newIa.SetT1(t1);
240 newIa.SetT2(t2);
241
242 // Check if the IA is to be added to the list of IANA or IATA options.
243 // If the IAID is already present, it is not added.
244 switch (optionType)
245 {
247 bool iaidPresent = false;
248 for (const auto& itr : m_ianaList)
249 {
250 if (itr.GetIaid() == newIa.GetIaid())
251 {
252 iaidPresent = true;
253 break;
254 }
255 }
256
257 if (!iaidPresent)
258 {
259 m_ianaList.push_back(newIa);
260 AddMessageLength(4 + optionLength);
261 }
262 break;
263 }
264
266 bool iaidPresent = false;
267 for (const auto& itr : m_iataList)
268 {
269 if (itr.GetIaid() == newIa.GetIaid())
270 {
271 iaidPresent = true;
272 break;
273 }
274 }
275
276 if (!iaidPresent)
277 {
278 m_iataList.push_back(newIa);
279 AddMessageLength(4 + optionLength);
280 }
281 break;
282 }
283
284 default:
285 break;
286 }
287
288 // Set the option flag to true.
289 m_options[optionType] = true;
290}
291
292void
294 Ipv6Address address,
295 uint32_t prefLifetime,
296 uint32_t validLifetime)
297{
298 bool isIana = false;
299 bool isIata = false;
300
301 // Check if IAID corresponds to an IANA option.
302 auto itr = m_ianaList.begin();
303 while (itr != m_ianaList.end())
304 {
305 if (iaid == (*itr).GetIaid())
306 {
307 isIana = true;
308 break;
309 }
310 itr++;
311 }
312
313 // Else, check if IAID corresponds to an IATA option.
314 if (!isIana)
315 {
316 itr = m_iataList.begin();
317 while (itr != m_iataList.end())
318 {
319 if (iaid == (*itr).GetIaid())
320 {
321 isIata = true;
322 break;
323 }
324 itr++;
325 }
326 }
327
328 if (!isIana && !isIata)
329 {
330 NS_LOG_ERROR("Given IAID does not exist, cannot add address.");
331 }
332
333 IaAddressOption adrOpt;
335
336 // Set length of IA Address option without including additional option list.
337 adrOpt.SetOptionLength(24);
338 adrOpt.SetIaAddress(address);
339 adrOpt.SetPreferredLifetime(prefLifetime);
340 adrOpt.SetValidLifetime(validLifetime);
341
342 (*itr).m_iaAddressOption.push_back(adrOpt);
343
344 // Add the address option length to the overall IANA or IATA length.
345 (*itr).SetOptionLength((*itr).GetOptionLength() + 28);
346
347 // Increase the total message length.
348 AddMessageLength(4 + 24);
349}
350
351std::map<Options::OptionType, bool>
353{
354 return m_options;
355}
356
357void
359{
363
365
366 // Increase the total message length.
368
369 // Set the option flag to true.
371}
372
375{
376 return m_len;
377}
378
379void
380Dhcp6Header::Print(std::ostream& os) const
381{
382 os << "(type=" << +(uint8_t)m_msgType << ")";
383}
384
385void
387{
388 Buffer::Iterator i = start;
389 uint32_t mTTid = (uint32_t)m_msgType << 24 | m_transactId;
390 i.WriteHtonU32(mTTid);
391
393 {
397 uint32_t size = duid.GetSerializedSize();
398 duid.Serialize(i);
399 i.Next(size);
400 }
402 {
406 uint32_t size = duid.GetSerializedSize();
407 duid.Serialize(i);
408 i.Next(size);
409 }
411 {
412 for (const auto& itr : m_ianaList)
413 {
414 i.WriteHtonU16((uint16_t)itr.GetOptionCode());
415 i.WriteHtonU16(itr.GetOptionLength());
416 i.WriteHtonU32(itr.GetIaid());
417 i.WriteHtonU32(itr.GetT1());
418 i.WriteHtonU32(itr.GetT2());
419
420 std::vector<IaAddressOption> iaAddresses = itr.m_iaAddressOption;
421 for (const auto& iaItr : iaAddresses)
422 {
423 i.WriteHtonU16((uint16_t)iaItr.GetOptionCode());
424 i.WriteHtonU16(iaItr.GetOptionLength());
425
426 Address addr = iaItr.GetIaAddress();
427 uint8_t addrBuf[16];
428 addr.CopyTo(addrBuf);
429 i.Write(addrBuf, 16);
430 i.WriteHtonU32(iaItr.GetPreferredLifetime());
431 i.WriteHtonU32(iaItr.GetValidLifetime());
432 }
433 }
434 }
436 {
440 }
442 {
445
446 std::vector<Options::OptionType> requestedOptions = m_optionRequest.GetRequestedOptions();
447 for (const auto& itr : requestedOptions)
448 {
449 i.WriteHtonU16(static_cast<uint16_t>(itr));
450 }
451 }
453 {
455 i.WriteHtonU16(4);
457 }
459 {
463
464 // Considering a maximum message length of 128 bytes (arbitrary).
465 uint8_t strBuf[128];
466 m_statusCode.GetStatusMessage().copy((char*)strBuf,
467 m_statusCode.GetStatusMessage().length());
468 strBuf[m_statusCode.GetOptionLength() - 2] = '\0';
469
470 i.Write(strBuf, m_statusCode.GetStatusMessage().length());
471 }
472}
473
476{
477 Buffer::Iterator i = start;
478 uint32_t cLen = i.GetSize();
479
480 uint32_t mTTid = i.ReadNtohU32();
481 m_msgType = (MessageType)(mTTid >> 24);
482 m_transactId = mTTid & 0x00FFFFFF;
483
484 uint32_t len = 4;
485 uint16_t option;
486 bool loop = true;
487 do
488 {
489 if (len + 2 <= cLen)
490 {
491 option = i.ReadNtohU16();
492 len += 2;
493 }
494 else
495 {
496 m_len = len;
497 return m_len;
498 }
499
500 auto opt = static_cast<Options::OptionType>(option);
501 switch (opt)
502 {
504 NS_LOG_INFO("Client Identifier Option");
505 if (len + 2 <= cLen)
506 {
509 len += 2;
510 if (len + m_clientIdentifier.GetOptionLength() <= cLen)
511 {
513
514 // Read DUID.
515 Duid duid;
516 uint32_t read = duid.Deserialize(i, duidLength - 4);
517 i.Next(read);
520 }
521 }
522 break;
523
525 NS_LOG_INFO("Server ID Option");
526 if (len + 2 <= cLen)
527 {
530 len += 2;
531 }
532 if (len + m_clientIdentifier.GetOptionLength() <= cLen)
533 {
535
536 // Read DUID.
537 Duid duid;
538 uint32_t read = duid.Deserialize(i, duidLength - 4);
539 i.Next(read);
542 }
543 break;
544
546 NS_LOG_INFO("IANA Option");
547 IaOptions iana;
548 uint32_t iaAddrOptLen = 0;
549 if (len + 2 <= cLen)
550 {
551 iana.SetOptionCode(opt);
553 iaAddrOptLen = iana.GetOptionLength();
554 len += 2;
555 }
556
557 if (len + 12 <= cLen)
558 {
559 iana.SetIaid(i.ReadNtohU32());
560 iana.SetT1(i.ReadNtohU32());
561 iana.SetT2(i.ReadNtohU32());
562 len += 12;
563 iaAddrOptLen -= 12;
564 }
565
566 uint32_t readLen = 0;
567 while (readLen < iaAddrOptLen)
568 {
569 IaAddressOption iaAddrOpt;
570 iaAddrOpt.SetOptionCode(static_cast<Options::OptionType>(i.ReadNtohU16()));
571 iaAddrOpt.SetOptionLength(i.ReadNtohU16());
572
573 uint8_t addrBuf[16];
574 i.Read(addrBuf, 16);
575 iaAddrOpt.SetIaAddress(Ipv6Address(addrBuf));
576
577 iaAddrOpt.SetPreferredLifetime(i.ReadNtohU32());
578 iaAddrOpt.SetValidLifetime(i.ReadNtohU32());
579
580 iana.m_iaAddressOption.push_back(iaAddrOpt);
581 len += 4 + iaAddrOpt.GetOptionLength();
582
583 readLen += 4 + iaAddrOpt.GetOptionLength();
584 }
585 m_ianaList.push_back(iana);
587 break;
588 }
589
591 NS_LOG_INFO("Elapsed Time Option");
592 if (len + 4 <= cLen)
593 {
598 len += 4;
599 }
600 else
601 {
602 NS_LOG_WARN("Malformed Packet");
603 return 0;
604 }
605 break;
606
608 NS_LOG_INFO("Option Request Option");
609 if (len + 2 <= cLen)
610 {
613 len += 2;
614 }
615 while (len + 2 <= cLen)
616 {
618 static_cast<Options::OptionType>(i.ReadNtohU16()));
619 len += 2;
620 }
622 break;
623
625 NS_LOG_INFO("Solicit Max RT Option");
626 if (len + 6 <= cLen)
627 {
628 i.ReadNtohU16();
630 len += 6;
631 }
633 break;
634
636 NS_LOG_INFO("Status Code Option");
637 if (len + 2 <= cLen)
638 {
641 len += 2;
642 }
643 if (len + 2 <= cLen)
644 {
646 len += 2;
647 }
648
649 if (len + (m_statusCode.GetOptionLength() - 2) <= cLen)
650 {
651 uint8_t msgLength = m_statusCode.GetOptionLength() - 2;
652 uint8_t strBuf[128];
653 i.Read(strBuf, msgLength);
654 strBuf[msgLength] = '\0';
655
656 std::string statusMsg((char*)strBuf);
658 len += msgLength;
659 }
661 break;
662
663 default:
664 NS_LOG_WARN("Unidentified Option " << option);
665 NS_LOG_WARN("Malformed Packet");
666 return 0;
667 }
668 } while (loop);
669
670 m_len = len;
671 return m_len;
672}
673} // namespace ns3
a polymophic address class
Definition address.h:90
uint32_t CopyTo(uint8_t buffer[MAX_SIZE]) const
Copy the address bytes into a buffer.
Definition address.cc:75
iterator in a Buffer instance
Definition buffer.h:89
void Write(const uint8_t *buffer, uint32_t size)
Definition buffer.cc:937
void Read(uint8_t *buffer, uint32_t size)
Definition buffer.cc:1114
void WriteHtonU16(uint16_t data)
Definition buffer.h:904
uint32_t ReadNtohU32()
Definition buffer.h:967
void WriteHtonU32(uint32_t data)
Definition buffer.h:922
uint16_t ReadNtohU16()
Definition buffer.h:943
uint32_t GetSize() const
Definition buffer.cc:1155
void Next()
go forward by one byte
Definition buffer.h:842
Implements the DHCPv6 header.
uint32_t GetSerializedSize() const override
IdentifierOption GetClientIdentifier()
Get the client identifier.
void AddElapsedTime(uint16_t timestamp)
Set the elapsed time option.
void AddServerIdentifier(Duid duid)
Add the server identifier option.
void ResetOptions()
Reset all options.
std::map< Options::OptionType, bool > GetOptionList()
Get list of all options set in the header.
uint32_t m_transactId
The transaction ID calculated by the client or the server.
std::vector< IaOptions > m_ianaList
Vector of IA_NA options.
void AddIdentifierOption(IdentifierOption &identifier, Options::OptionType optionType, Duid duid)
Add an identifier option to the header.
void Print(std::ostream &os) const override
void AddClientIdentifier(Duid duid)
Add the client identifier option.
IdentifierOption m_serverIdentifier
The server identifier option.
static TypeId GetTypeId()
Get the type ID.
uint32_t Deserialize(Buffer::Iterator start) override
ElapsedTimeOption m_elapsedTime
The amount of time since the client began the transaction.
uint32_t GetTransactId() const
Get the transaction ID.
RequestOptions m_optionRequest
List of additional options requested.
void AddAddress(uint32_t iaid, Ipv6Address address, uint32_t prefLifetime, uint32_t validLifetime)
Add IA address option to the IANA or IATA.
MessageType GetMessageType() const
Get the type of message.
std::map< Options::OptionType, bool > m_options
Options present in the header, indexed by option code.
void AddSolMaxRt()
Add the SOL_MAX_RT option.
void AddIataOption(uint32_t iaid)
Add IATA option.
void AddOptionRequest(Options::OptionType optionType)
Request additional options.
std::vector< IaOptions > m_iataList
Vector of IA_TA options.
uint32_t m_len
The length of the message.
MessageType
Enum to identify the message type.
void HandleOptionRequest(std::vector< Options::OptionType > requestedOptions)
Handle all options requested by client.
void AddStatusCode(Options::StatusCodeValues statusCode, std::string statusMsg)
Add the status code option.
void AddIanaOption(uint32_t iaid, uint32_t t1, uint32_t t2)
Add IANA option.
MessageType m_msgType
The message type.
void SetMessageType(MessageType msgType)
Set the message type.
void AddMessageLength(uint32_t len)
Update the message length.
std::vector< IaOptions > GetIanaOptions()
Get the list of IA_NA options.
void AddIaOption(Options::OptionType optionType, uint32_t iaid, uint32_t t1=0, uint32_t t2=0)
Add IANA or IATA option to the header.
IdentifierOption m_clientIdentifier
The client identifier option.
uint32_t m_solMaxRt
Default value for SOL_MAX_RT option.
StatusCodeOption m_statusCode
(optional) The status code of the operation just performed.
RequestOptions GetOptionRequest()
Get the option request option.
Dhcp6Header()
Default constructor.
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
IdentifierOption GetServerIdentifier()
Get the server identifier.
StatusCodeOption GetStatusCodeOption()
Get the status code of the operation.
void Serialize(Buffer::Iterator start) const override
void SetTransactId(uint32_t transactId)
Set the transaction ID.
Implements the unique identifier for DHCPv6.
Definition dhcp6-duid.h:27
uint32_t Deserialize(Buffer::Iterator start, uint32_t len)
Deserialize the DUID.
uint8_t GetLength() const
Get the length of the DUID.
Definition dhcp6-duid.cc:69
void Serialize(Buffer::Iterator start) const
Serialize the DUID.
uint32_t GetSerializedSize() const
Get the DUID serialized size.
Protocol header serialization and deserialization.
Definition header.h:33
Implements the IA Address options.
void SetPreferredLifetime(uint32_t preferredLifetime)
Set the preferred lifetime.
void SetValidLifetime(uint32_t validLifetime)
Set the valid lifetime.
void SetIaAddress(Ipv6Address iaAddress)
Set the IA Address.
Implements the IANA and IATA options.
std::vector< IaAddressOption > m_iaAddressOption
The list of IA Address options associated with the IANA.
void SetT1(uint32_t t1)
Set the time interval in seconds after which the client contacts the server which provided the addres...
void SetT2(uint32_t t2)
Set the time interval in seconds after which the client contacts any available server to extend the a...
uint32_t GetIaid() const
Get the unique identifier for the given IANA or IATA.
void SetIaid(uint32_t iaid)
Set the unique identifier for the given IANA or IATA.
Implements the client and server identifier options.
void SetDuid(Duid duid)
Set the DUID.
Duid GetDuid() const
Get the DUID object.
void SetOptionValue(T optionValue)
Set the option value.
T GetOptionValue() const
Get the option value.
Describes an IPv6 address.
StatusCodeValues
Enum to identify the status code of the operation.
void SetOptionCode(OptionType code)
Set the option code.
uint16_t GetOptionLength() const
Get the option length.
OptionType GetOptionCode() const
Get the option code.
OptionType
Enum to identify the option type.
void SetOptionLength(uint16_t length)
Set the option length.
Implements the Option Request option.
std::vector< OptionType > GetRequestedOptions() const
Get the option values.
void AddRequestedOption(OptionType requestedOption)
Set the option values.
Implements the Status Code option.
void SetStatusCode(StatusCodeValues statusCode)
Set the status code of the operation.
StatusCodeValues GetStatusCode() const
Get the status code of the operation.
std::string GetStatusMessage() const
Get the status message of the operation.
void SetStatusMessage(std::string statusMessage)
Set the status message of the operation.
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition log.h:243
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition log.h:250
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Every class exported by the ns3 library is enclosed in the ns3 namespace.