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 = duid.GetSerializedSize();
146
147 // Set the option code, length, hardware type, link layer address.
148 identifier.SetOptionCode(optionType);
149 identifier.SetOptionLength(duidLength);
150 identifier.SetDuid(duid);
151
152 // Increase the total length by (4 + duidLength) bytes.
153 AddMessageLength(4 + duidLength);
154
155 // Set the option flag to true.
156 m_options[optionType] = true;
157}
158
164
165void
167{
168 // Check if this is the first option request.
169 if (m_optionRequest.GetOptionLength() == 0)
170 {
172 }
173
174 // Set the option code, length, and add the requested option.
176 m_optionRequest.SetOptionLength(m_optionRequest.GetOptionLength() + 2);
177 m_optionRequest.AddRequestedOption(optionType);
178
179 // Increase the total length by 2 bytes.
181
182 // Set the option flag to true.
184}
185
186void
187Dhcp6Header::HandleOptionRequest(std::vector<Options::OptionType> requestedOptions)
188{
189 // Currently, only Options::OptionType::OPTION_SOL_MAX_RT is supported.
190 for (auto itr : requestedOptions)
191 {
192 switch (itr)
193 {
195 AddSolMaxRt();
196 break;
197 default:
198 NS_LOG_WARN("Requested Option not supported.");
199 }
200 }
201}
202
203void
205{
206 // Increase the total message length.
207 // 4 bytes - for option code + option length.
208 // 4 bytes - for the option value.
209 AddMessageLength(4 + 4);
210
212}
213
214void
219
220void
225
226void
228{
229 // Create a new identity association.
230 IaOptions newIa;
231 newIa.SetOptionCode(optionType);
232
233 // Minimum option length of an IA is 12 bytes.
234 uint16_t optionLength = 12;
235
236 newIa.SetOptionLength(optionLength);
237 newIa.SetIaid(iaid);
238 newIa.SetT1(t1);
239 newIa.SetT2(t2);
240
241 // Check if the IA is to be added to the list of IANA or IATA options.
242 // If the IAID is already present, it is not added.
243 switch (optionType)
244 {
246 bool iaidPresent = false;
247 for (const auto& itr : m_ianaList)
248 {
249 if (itr.GetIaid() == newIa.GetIaid())
250 {
251 iaidPresent = true;
252 break;
253 }
254 }
255
256 if (!iaidPresent)
257 {
258 m_ianaList.push_back(newIa);
259 AddMessageLength(4 + optionLength);
260 }
261 break;
262 }
263
265 bool iaidPresent = false;
266 for (const auto& itr : m_iataList)
267 {
268 if (itr.GetIaid() == newIa.GetIaid())
269 {
270 iaidPresent = true;
271 break;
272 }
273 }
274
275 if (!iaidPresent)
276 {
277 m_iataList.push_back(newIa);
278 AddMessageLength(4 + optionLength);
279 }
280 break;
281 }
282
283 default:
284 break;
285 }
286
287 // Set the option flag to true.
288 m_options[optionType] = true;
289}
290
291void
293 Ipv6Address address,
294 uint32_t prefLifetime,
295 uint32_t validLifetime)
296{
297 bool isIana = false;
298 bool isIata = false;
299
300 // Check if IAID corresponds to an IANA option.
301 auto itr = m_ianaList.begin();
302 while (itr != m_ianaList.end())
303 {
304 if (iaid == (*itr).GetIaid())
305 {
306 isIana = true;
307 break;
308 }
309 itr++;
310 }
311
312 // Else, check if IAID corresponds to an IATA option.
313 if (!isIana)
314 {
315 itr = m_iataList.begin();
316 while (itr != m_iataList.end())
317 {
318 if (iaid == (*itr).GetIaid())
319 {
320 isIata = true;
321 break;
322 }
323 itr++;
324 }
325 }
326
327 if (!isIana && !isIata)
328 {
329 NS_LOG_ERROR("Given IAID does not exist, cannot add address.");
330 }
331
332 IaAddressOption adrOpt;
334
335 // Set length of IA Address option without including additional option list.
336 adrOpt.SetOptionLength(24);
337 adrOpt.SetIaAddress(address);
338 adrOpt.SetPreferredLifetime(prefLifetime);
339 adrOpt.SetValidLifetime(validLifetime);
340
341 (*itr).m_iaAddressOption.push_back(adrOpt);
342
343 // Add the address option length to the overall IANA or IATA length.
344 (*itr).SetOptionLength((*itr).GetOptionLength() + 28);
345
346 // Increase the total message length.
347 AddMessageLength(4 + 24);
348}
349
350std::map<Options::OptionType, bool>
352{
353 return m_options;
354}
355
356void
358{
360 m_statusCode.SetStatusCode(status);
361 m_statusCode.SetStatusMessage(statusMsg);
362
363 m_statusCode.SetOptionLength(2 + m_statusCode.GetStatusMessage().length());
364
365 // Increase the total message length.
366 AddMessageLength(4 + m_statusCode.GetOptionLength());
367
368 // Set the option flag to true.
370}
371
374{
375 return m_len;
376}
377
378void
379Dhcp6Header::Print(std::ostream& os) const
380{
381 os << "(type=" << +(uint8_t)m_msgType << ")";
382}
383
384void
386{
387 Buffer::Iterator i = start;
388 uint32_t mTTid = (uint32_t)m_msgType << 24 | m_transactId;
389 i.WriteHtonU32(mTTid);
390
392 {
393 i.WriteHtonU16((uint16_t)m_clientIdentifier.GetOptionCode());
394 i.WriteHtonU16(m_clientIdentifier.GetOptionLength());
395 Duid duid = m_clientIdentifier.GetDuid();
396 uint32_t size = duid.GetSerializedSize();
397 duid.Serialize(i);
398 i.Next(size);
399 }
401 {
402 i.WriteHtonU16((uint16_t)m_serverIdentifier.GetOptionCode());
403 i.WriteHtonU16(m_serverIdentifier.GetOptionLength());
404 Duid duid = m_serverIdentifier.GetDuid();
405 uint32_t size = duid.GetSerializedSize();
406 duid.Serialize(i);
407 i.Next(size);
408 }
410 {
411 for (const auto& itr : m_ianaList)
412 {
413 i.WriteHtonU16((uint16_t)itr.GetOptionCode());
414 i.WriteHtonU16(itr.GetOptionLength());
415 i.WriteHtonU32(itr.GetIaid());
416 i.WriteHtonU32(itr.GetT1());
417 i.WriteHtonU32(itr.GetT2());
418
419 std::vector<IaAddressOption> iaAddresses = itr.m_iaAddressOption;
420 for (const auto& iaItr : iaAddresses)
421 {
422 i.WriteHtonU16((uint16_t)iaItr.GetOptionCode());
423 i.WriteHtonU16(iaItr.GetOptionLength());
424
425 Address addr = iaItr.GetIaAddress();
426 uint8_t addrBuf[16];
427 addr.CopyTo(addrBuf);
428 i.Write(addrBuf, 16);
429 i.WriteHtonU32(iaItr.GetPreferredLifetime());
430 i.WriteHtonU32(iaItr.GetValidLifetime());
431 }
432 }
433 }
435 {
436 i.WriteHtonU16((uint16_t)m_elapsedTime.GetOptionCode());
437 i.WriteHtonU16(m_elapsedTime.GetOptionLength());
438 i.WriteHtonU16(m_elapsedTime.GetOptionValue());
439 }
441 {
442 i.WriteHtonU16((uint16_t)m_optionRequest.GetOptionCode());
443 i.WriteHtonU16(m_optionRequest.GetOptionLength());
444
445 std::vector<Options::OptionType> requestedOptions = m_optionRequest.GetRequestedOptions();
446 for (const auto& itr : requestedOptions)
447 {
448 i.WriteHtonU16(static_cast<uint16_t>(itr));
449 }
450 }
452 {
454 i.WriteHtonU16(4);
456 }
458 {
460 i.WriteHtonU16(m_statusCode.GetOptionLength());
461 i.WriteHtonU16((uint16_t)m_statusCode.GetStatusCode());
462
463 // Considering a maximum message length of 128 bytes (arbitrary).
464 uint8_t strBuf[128];
465 m_statusCode.GetStatusMessage().copy((char*)strBuf,
466 m_statusCode.GetStatusMessage().length());
467 strBuf[m_statusCode.GetOptionLength() - 2] = '\0';
468
469 i.Write(strBuf, m_statusCode.GetStatusMessage().length());
470 }
471}
472
475{
476 Buffer::Iterator i = start;
477 uint32_t cLen = i.GetSize();
478
479 uint32_t mTTid = i.ReadNtohU32();
480 m_msgType = (MessageType)(mTTid >> 24);
481 m_transactId = mTTid & 0x00FFFFFF;
482
483 uint32_t len = 4;
484 uint16_t option;
485 bool loop = true;
486 do
487 {
488 if (len + 2 <= cLen)
489 {
490 option = i.ReadNtohU16();
491 len += 2;
492 }
493 else
494 {
495 m_len = len;
496 return m_len;
497 }
498
499 auto opt = static_cast<Options::OptionType>(option);
500 switch (opt)
501 {
503 NS_LOG_INFO("Client Identifier Option");
504 if (len + 2 <= cLen)
505 {
506 m_clientIdentifier.SetOptionCode(opt);
507 m_clientIdentifier.SetOptionLength(i.ReadNtohU16());
508 len += 2;
509 if (len + m_clientIdentifier.GetOptionLength() <= cLen)
510 {
511 uint32_t duidLength = m_clientIdentifier.GetOptionLength();
512
513 // Read DUID.
514 Duid duid;
515 uint32_t read = duid.Deserialize(i, duidLength);
516 i.Next(read);
517 m_clientIdentifier.SetDuid(duid);
518 len += m_clientIdentifier.GetOptionLength();
519 }
520 }
521 break;
522
524 NS_LOG_INFO("Server ID Option");
525 if (len + 2 <= cLen)
526 {
527 m_serverIdentifier.SetOptionCode(opt);
528 m_serverIdentifier.SetOptionLength(i.ReadNtohU16());
529 len += 2;
530 }
531 if (len + m_clientIdentifier.GetOptionLength() <= cLen)
532 {
533 uint32_t duidLength = m_serverIdentifier.GetOptionLength();
534
535 // Read DUID.
536 Duid duid;
537 uint32_t read = duid.Deserialize(i, duidLength);
538 i.Next(read);
539 m_serverIdentifier.SetDuid(duid);
540 len += m_serverIdentifier.GetOptionLength();
541 }
542 break;
543
545 NS_LOG_INFO("IANA Option");
546 IaOptions iana;
547 uint32_t iaAddrOptLen = 0;
548 if (len + 2 <= cLen)
549 {
550 iana.SetOptionCode(opt);
552 iaAddrOptLen = iana.GetOptionLength();
553 len += 2;
554 }
555
556 if (len + 12 <= cLen)
557 {
558 iana.SetIaid(i.ReadNtohU32());
559 iana.SetT1(i.ReadNtohU32());
560 iana.SetT2(i.ReadNtohU32());
561 len += 12;
562 iaAddrOptLen -= 12;
563 }
564
565 uint32_t readLen = 0;
566 while (readLen < iaAddrOptLen)
567 {
568 IaAddressOption iaAddrOpt;
569 iaAddrOpt.SetOptionCode(static_cast<Options::OptionType>(i.ReadNtohU16()));
570 iaAddrOpt.SetOptionLength(i.ReadNtohU16());
571
572 uint8_t addrBuf[16];
573 i.Read(addrBuf, 16);
574 iaAddrOpt.SetIaAddress(Ipv6Address(addrBuf));
575
576 iaAddrOpt.SetPreferredLifetime(i.ReadNtohU32());
577 iaAddrOpt.SetValidLifetime(i.ReadNtohU32());
578
579 iana.m_iaAddressOption.push_back(iaAddrOpt);
580 len += 4 + iaAddrOpt.GetOptionLength();
581
582 readLen += 4 + iaAddrOpt.GetOptionLength();
583 }
584 m_ianaList.push_back(iana);
586 break;
587 }
588
590 NS_LOG_INFO("Elapsed Time Option");
591 if (len + 4 <= cLen)
592 {
593 m_elapsedTime.SetOptionCode(opt);
594 m_elapsedTime.SetOptionLength(i.ReadNtohU16());
595 m_elapsedTime.SetOptionValue(i.ReadNtohU16());
597 len += 4;
598 }
599 else
600 {
601 NS_LOG_WARN("Malformed Packet");
602 return 0;
603 }
604 break;
605
607 NS_LOG_INFO("Option Request Option");
608 if (len + 2 <= cLen)
609 {
610 m_optionRequest.SetOptionCode(opt);
611 m_optionRequest.SetOptionLength(i.ReadNtohU16());
612 len += 2;
613 }
614 while (len + 2 <= cLen)
615 {
616 m_optionRequest.AddRequestedOption(
617 static_cast<Options::OptionType>(i.ReadNtohU16()));
618 len += 2;
619 }
621 break;
622
624 NS_LOG_INFO("Solicit Max RT Option");
625 if (len + 6 <= cLen)
626 {
627 i.ReadNtohU16();
629 len += 6;
630 }
632 break;
633
635 NS_LOG_INFO("Status Code Option");
636 if (len + 2 <= cLen)
637 {
638 m_statusCode.SetOptionCode(opt);
639 m_statusCode.SetOptionLength(i.ReadNtohU16());
640 len += 2;
641 }
642 if (len + 2 <= cLen)
643 {
645 len += 2;
646 }
647
648 if (len + (m_statusCode.GetOptionLength() - 2) <= cLen)
649 {
650 uint8_t msgLength = m_statusCode.GetOptionLength() - 2;
651 uint8_t strBuf[128];
652 i.Read(strBuf, msgLength);
653 strBuf[msgLength] = '\0';
654
655 std::string statusMsg((char*)strBuf);
656 m_statusCode.SetStatusMessage(statusMsg);
657 len += msgLength;
658 }
660 break;
661
662 default:
663 NS_LOG_WARN("Unidentified Option " << option);
664 NS_LOG_WARN("Malformed Packet");
665 return 0;
666 }
667 } while (loop);
668
669 m_len = len;
670 return m_len;
671}
672} // 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.
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: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_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.