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),
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.
118 m_elapsedTime.SetOptionLength(2);
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 uint16_t duidLength = 0;
146 switch (duid.GetDuidType())
147 {
148 case Duid::Type::LL:
149 // DUID type (2 bytes) + hw type (2 bytes) + Link-layer Address (variable)
150 duidLength = 2 + 2 + duid.GetLength();
151 break;
152 case Duid::Type::LLT:
153 // DUID type (2 bytes) + hw type (2 bytes) + time (4 bytes) + Link-layer Address (variable)
154 duidLength = 2 + 2 + 4 + duid.GetLength();
155 break;
156 case Duid::Type::EN:
157 case Duid::Type::UUID:
158 NS_ASSERT_MSG(false, "Duid: Unsupported DUID type.");
159 break;
160 }
161
162 // Set the option code, length, hardware type, link layer address.
163 identifier.SetOptionCode(optionType);
164 identifier.SetOptionLength(duidLength);
165 identifier.SetDuid(duid);
166
167 // Increase the total length by (4 + duidLength) bytes.
168 AddMessageLength(4 + duidLength);
169
170 // Set the option flag to true.
171 m_options[optionType] = true;
172}
173
179
180void
182{
183 // Check if this is the first option request.
184 if (m_optionRequest.GetOptionLength() == 0)
185 {
187 }
188
189 // Set the option code, length, and add the requested option.
191 m_optionRequest.SetOptionLength(m_optionRequest.GetOptionLength() + 2);
192 m_optionRequest.AddRequestedOption(optionType);
193
194 // Increase the total length by 2 bytes.
196
197 // Set the option flag to true.
199}
200
201void
202Dhcp6Header::HandleOptionRequest(std::vector<Options::OptionType> requestedOptions)
203{
204 // Currently, only Options::OptionType::OPTION_SOL_MAX_RT is supported.
205 for (auto itr : requestedOptions)
206 {
207 switch (itr)
208 {
210 AddSolMaxRt();
211 break;
212 default:
213 NS_LOG_WARN("Requested Option not supported.");
214 }
215 }
216}
217
218void
220{
221 // Increase the total message length.
222 // 4 bytes - for option code + option length.
223 // 4 bytes - for the option value.
224 AddMessageLength(4 + 4);
225
227}
228
229void
234
235void
240
241void
243{
244 // Create a new identity association.
245 IaOptions newIa;
246 newIa.SetOptionCode(optionType);
247
248 // Minimum option length of an IA is 12 bytes.
249 uint16_t optionLength = 12;
250
251 newIa.SetOptionLength(optionLength);
252 newIa.SetIaid(iaid);
253 newIa.SetT1(t1);
254 newIa.SetT2(t2);
255
256 // Check if the IA is to be added to the list of IANA or IATA options.
257 // If the IAID is already present, it is not added.
258 switch (optionType)
259 {
261 bool iaidPresent = false;
262 for (const auto& itr : m_ianaList)
263 {
264 if (itr.GetIaid() == newIa.GetIaid())
265 {
266 iaidPresent = true;
267 break;
268 }
269 }
270
271 if (!iaidPresent)
272 {
273 m_ianaList.push_back(newIa);
274 AddMessageLength(4 + optionLength);
275 }
276 break;
277 }
278
280 bool iaidPresent = false;
281 for (const auto& itr : m_iataList)
282 {
283 if (itr.GetIaid() == newIa.GetIaid())
284 {
285 iaidPresent = true;
286 break;
287 }
288 }
289
290 if (!iaidPresent)
291 {
292 m_iataList.push_back(newIa);
293 AddMessageLength(4 + optionLength);
294 }
295 break;
296 }
297
298 default:
299 break;
300 }
301
302 // Set the option flag to true.
303 m_options[optionType] = true;
304}
305
306void
308 Ipv6Address address,
309 uint32_t prefLifetime,
310 uint32_t validLifetime)
311{
312 bool isIana = false;
313 bool isIata = false;
314
315 // Check if IAID corresponds to an IANA option.
316 auto itr = m_ianaList.begin();
317 while (itr != m_ianaList.end())
318 {
319 if (iaid == (*itr).GetIaid())
320 {
321 isIana = true;
322 break;
323 }
324 itr++;
325 }
326
327 // Else, check if IAID corresponds to an IATA option.
328 if (!isIana)
329 {
330 itr = m_iataList.begin();
331 while (itr != m_iataList.end())
332 {
333 if (iaid == (*itr).GetIaid())
334 {
335 isIata = true;
336 break;
337 }
338 itr++;
339 }
340 }
341
342 if (!isIana && !isIata)
343 {
344 NS_LOG_ERROR("Given IAID does not exist, cannot add address.");
345 }
346
347 IaAddressOption adrOpt;
349
350 // Set length of IA Address option without including additional option list.
351 adrOpt.SetOptionLength(24);
352 adrOpt.SetIaAddress(address);
353 adrOpt.SetPreferredLifetime(prefLifetime);
354 adrOpt.SetValidLifetime(validLifetime);
355
356 (*itr).m_iaAddressOption.push_back(adrOpt);
357
358 // Add the address option length to the overall IANA or IATA length.
359 (*itr).SetOptionLength((*itr).GetOptionLength() + 28);
360
361 // Increase the total message length.
362 AddMessageLength(4 + 24);
363}
364
365std::map<Options::OptionType, bool>
367{
368 return m_options;
369}
370
371void
373{
375 m_statusCode.SetStatusCode(status);
376 m_statusCode.SetStatusMessage(statusMsg);
377
378 m_statusCode.SetOptionLength(2 + m_statusCode.GetStatusMessage().length());
379
380 // Increase the total message length.
381 AddMessageLength(4 + m_statusCode.GetOptionLength());
382
383 // Set the option flag to true.
385}
386
389{
390 return m_len;
391}
392
393void
394Dhcp6Header::Print(std::ostream& os) const
395{
396 os << "(type=" << +(uint8_t)m_msgType << ")";
397}
398
399void
401{
402 Buffer::Iterator i = start;
403 uint32_t mTTid = (uint32_t)m_msgType << 24 | m_transactId;
404 i.WriteHtonU32(mTTid);
405
407 {
408 i.WriteHtonU16((uint16_t)m_clientIdentifier.GetOptionCode());
409 i.WriteHtonU16(m_clientIdentifier.GetOptionLength());
410 Duid duid = m_clientIdentifier.GetDuid();
411 uint32_t size = duid.GetSerializedSize();
412 duid.Serialize(i);
413 i.Next(size);
414 }
416 {
417 i.WriteHtonU16((uint16_t)m_serverIdentifier.GetOptionCode());
418 i.WriteHtonU16(m_serverIdentifier.GetOptionLength());
419 Duid duid = m_serverIdentifier.GetDuid();
420 uint32_t size = duid.GetSerializedSize();
421 duid.Serialize(i);
422 i.Next(size);
423 }
425 {
426 for (const auto& itr : m_ianaList)
427 {
428 i.WriteHtonU16((uint16_t)itr.GetOptionCode());
429 i.WriteHtonU16(itr.GetOptionLength());
430 i.WriteHtonU32(itr.GetIaid());
431 i.WriteHtonU32(itr.GetT1());
432 i.WriteHtonU32(itr.GetT2());
433
434 std::vector<IaAddressOption> iaAddresses = itr.m_iaAddressOption;
435 for (const auto& iaItr : iaAddresses)
436 {
437 i.WriteHtonU16((uint16_t)iaItr.GetOptionCode());
438 i.WriteHtonU16(iaItr.GetOptionLength());
439
440 Address addr = iaItr.GetIaAddress();
441 uint8_t addrBuf[16];
442 addr.CopyTo(addrBuf);
443 i.Write(addrBuf, 16);
444 i.WriteHtonU32(iaItr.GetPreferredLifetime());
445 i.WriteHtonU32(iaItr.GetValidLifetime());
446 }
447 }
448 }
450 {
451 i.WriteHtonU16((uint16_t)m_elapsedTime.GetOptionCode());
452 i.WriteHtonU16(m_elapsedTime.GetOptionLength());
453 i.WriteHtonU16(m_elapsedTime.GetOptionValue());
454 }
456 {
457 i.WriteHtonU16((uint16_t)m_optionRequest.GetOptionCode());
458 i.WriteHtonU16(m_optionRequest.GetOptionLength());
459
460 std::vector<Options::OptionType> requestedOptions = m_optionRequest.GetRequestedOptions();
461 for (const auto& itr : requestedOptions)
462 {
463 i.WriteHtonU16(static_cast<uint16_t>(itr));
464 }
465 }
467 {
469 i.WriteHtonU16(4);
471 }
473 {
475 i.WriteHtonU16(m_statusCode.GetOptionLength());
476 i.WriteHtonU16((uint16_t)m_statusCode.GetStatusCode());
477
478 // Considering a maximum message length of 128 bytes (arbitrary).
479 uint8_t strBuf[128];
480 m_statusCode.GetStatusMessage().copy((char*)strBuf,
481 m_statusCode.GetStatusMessage().length());
482 strBuf[m_statusCode.GetOptionLength() - 2] = '\0';
483
484 i.Write(strBuf, m_statusCode.GetStatusMessage().length());
485 }
486}
487
490{
491 Buffer::Iterator i = start;
492 uint32_t cLen = i.GetSize();
493
494 uint32_t mTTid = i.ReadNtohU32();
495 m_msgType = (MessageType)(mTTid >> 24);
496 m_transactId = mTTid & 0x00FFFFFF;
497
498 uint32_t len = 4;
499 uint16_t option;
500 bool loop = true;
501 do
502 {
503 if (len + 2 <= cLen)
504 {
505 option = i.ReadNtohU16();
506 len += 2;
507 }
508 else
509 {
510 m_len = len;
511 return m_len;
512 }
513
514 auto opt = static_cast<Options::OptionType>(option);
515 switch (opt)
516 {
518 NS_LOG_INFO("Client Identifier Option");
519 if (len + 2 <= cLen)
520 {
521 m_clientIdentifier.SetOptionCode(opt);
522 m_clientIdentifier.SetOptionLength(i.ReadNtohU16());
523 len += 2;
524 if (len + m_clientIdentifier.GetOptionLength() <= cLen)
525 {
526 uint32_t duidLength = m_clientIdentifier.GetOptionLength();
527
528 // Read DUID.
529 Duid duid;
530 uint32_t read = duid.Deserialize(i, duidLength);
531 i.Next(read);
532 m_clientIdentifier.SetDuid(duid);
533 len += m_clientIdentifier.GetOptionLength();
534 }
535 }
536 break;
537
539 NS_LOG_INFO("Server ID Option");
540 if (len + 2 <= cLen)
541 {
542 m_serverIdentifier.SetOptionCode(opt);
543 m_serverIdentifier.SetOptionLength(i.ReadNtohU16());
544 len += 2;
545 }
546 if (len + m_clientIdentifier.GetOptionLength() <= cLen)
547 {
548 uint32_t duidLength = m_serverIdentifier.GetOptionLength();
549
550 // Read DUID.
551 Duid duid;
552 uint32_t read = duid.Deserialize(i, duidLength);
553 i.Next(read);
554 m_serverIdentifier.SetDuid(duid);
555 len += m_serverIdentifier.GetOptionLength();
556 }
557 break;
558
560 NS_LOG_INFO("IANA Option");
561 IaOptions iana;
562 uint32_t iaAddrOptLen = 0;
563 if (len + 2 <= cLen)
564 {
565 iana.SetOptionCode(opt);
567 iaAddrOptLen = iana.GetOptionLength();
568 len += 2;
569 }
570
571 if (len + 12 <= cLen)
572 {
573 iana.SetIaid(i.ReadNtohU32());
574 iana.SetT1(i.ReadNtohU32());
575 iana.SetT2(i.ReadNtohU32());
576 len += 12;
577 iaAddrOptLen -= 12;
578 }
579
580 uint32_t readLen = 0;
581 while (readLen < iaAddrOptLen)
582 {
583 IaAddressOption iaAddrOpt;
584 iaAddrOpt.SetOptionCode(static_cast<Options::OptionType>(i.ReadNtohU16()));
585 iaAddrOpt.SetOptionLength(i.ReadNtohU16());
586
587 uint8_t addrBuf[16];
588 i.Read(addrBuf, 16);
589 iaAddrOpt.SetIaAddress(Ipv6Address(addrBuf));
590
591 iaAddrOpt.SetPreferredLifetime(i.ReadNtohU32());
592 iaAddrOpt.SetValidLifetime(i.ReadNtohU32());
593
594 iana.m_iaAddressOption.push_back(iaAddrOpt);
595 len += 4 + iaAddrOpt.GetOptionLength();
596
597 readLen += 4 + iaAddrOpt.GetOptionLength();
598 }
599 m_ianaList.push_back(iana);
601 break;
602 }
603
605 NS_LOG_INFO("Elapsed Time Option");
606 if (len + 4 <= cLen)
607 {
608 m_elapsedTime.SetOptionCode(opt);
609 m_elapsedTime.SetOptionLength(i.ReadNtohU16());
610 m_elapsedTime.SetOptionValue(i.ReadNtohU16());
612 len += 4;
613 }
614 else
615 {
616 NS_LOG_WARN("Malformed Packet");
617 return 0;
618 }
619 break;
620
622 NS_LOG_INFO("Option Request Option");
623 if (len + 2 <= cLen)
624 {
625 m_optionRequest.SetOptionCode(opt);
626 m_optionRequest.SetOptionLength(i.ReadNtohU16());
627 len += 2;
628 }
629 while (len + 2 <= cLen)
630 {
631 m_optionRequest.AddRequestedOption(
632 static_cast<Options::OptionType>(i.ReadNtohU16()));
633 len += 2;
634 }
636 break;
637
639 NS_LOG_INFO("Solicit Max RT Option");
640 if (len + 6 <= cLen)
641 {
642 i.ReadNtohU16();
644 len += 6;
645 }
647 break;
648
650 NS_LOG_INFO("Status Code Option");
651 if (len + 2 <= cLen)
652 {
653 m_statusCode.SetOptionCode(opt);
654 m_statusCode.SetOptionLength(i.ReadNtohU16());
655 len += 2;
656 }
657 if (len + 2 <= cLen)
658 {
660 len += 2;
661 }
662
663 if (len + (m_statusCode.GetOptionLength() - 2) <= cLen)
664 {
665 uint8_t msgLength = m_statusCode.GetOptionLength() - 2;
666 uint8_t strBuf[128];
667 i.Read(strBuf, msgLength);
668 strBuf[msgLength] = '\0';
669
670 std::string statusMsg((char*)strBuf);
671 m_statusCode.SetStatusMessage(statusMsg);
672 len += msgLength;
673 }
675 break;
676
677 default:
678 NS_LOG_WARN("Unidentified Option " << option);
679 NS_LOG_WARN("Malformed Packet");
680 return 0;
681 }
682 } while (loop);
683
684 m_len = len;
685 return m_len;
686}
687} // namespace ns3
a polymophic address class
Definition address.h:114
uint32_t CopyTo(uint8_t buffer[MAX_SIZE]) const
Copy the address bytes into a buffer.
Definition address.cc:70
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:916
uint32_t ReadNtohU32()
Definition buffer.h:979
void WriteHtonU32(uint32_t data)
Definition buffer.h:934
uint16_t ReadNtohU16()
Definition buffer.h:955
uint32_t GetSize() const
Definition buffer.cc:1155
void Next()
go forward by one byte
Definition buffer.h:854
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:31
void Serialize(Buffer::Iterator start) const
Serialize the DUID.
uint32_t GetSerializedSize() const
Get the DUID serialized size.
Type GetDuidType() const
Get the DUID type.
Definition dhcp6-duid.cc:43
Protocol header serialization and deserialization.
Definition header.h:36
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.
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
Enum to identify the option type.
void SetOptionLength(uint16_t length)
Set the option length.
Implements the Option Request option.
Implements the Status Code option.
a unique identifier for an interface.
Definition type-id.h:50
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:999
#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
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition log.h:246
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#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:253
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:267
Every class exported by the ns3 library is enclosed in the ns3 namespace.