1 /*
2  *  Copyright (c) 2016, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for DHCPv6 Service.
32  */
33 
34 #ifndef DHCP6_HPP_
35 #define DHCP6_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE || OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
40 
41 #include "common/clearable.hpp"
42 #include "common/equatable.hpp"
43 #include "common/message.hpp"
44 #include "common/random.hpp"
45 #include "mac/mac_types.hpp"
46 #include "net/udp6.hpp"
47 
48 namespace ot {
49 namespace Dhcp6 {
50 
51 using ot::Encoding::BigEndian::HostSwap16;
52 using ot::Encoding::BigEndian::HostSwap32;
53 
54 /**
55  * @addtogroup core-dhcp6
56  *
57  * @brief
58  *   This module includes definitions for DHCPv6.
59  *
60  * @{
61  *
62  */
63 
64 constexpr uint16_t kDhcpClientPort       = 546;
65 constexpr uint16_t kDhcpServerPort       = 547;
66 constexpr uint16_t kHardwareTypeEui64    = 27;
67 constexpr uint16_t kHardwareTypeEthernet = 1;
68 
69 /**
70  * DHCPv6 Message Types
71  *
72  */
73 enum Type : uint8_t
74 {
75     kTypeNone               = 0,
76     kTypeSolicit            = 1,
77     kTypeAdvertise          = 2,
78     kTypeRequest            = 3,
79     kTypeConfirm            = 4,
80     kTypeRenew              = 5,
81     kTypeRebind             = 6,
82     kTypeReply              = 7,
83     kTypeRelease            = 8,
84     kTypeDecline            = 9,
85     kTypeReconfigure        = 10,
86     kTypeInformationRequest = 11,
87     kTypeRelayForward       = 12,
88     kTypeRelayReply         = 13,
89     kTypeLeaseQuery         = 14,
90     kTypeLeaseQueryReply    = 15,
91 };
92 
93 /**
94  * Represents a DHCP6 transaction identifier.
95  *
96  */
97 OT_TOOL_PACKED_BEGIN
98 class TransactionId : public Equatable<TransactionId>, public Clearable<TransactionId>
99 {
100 public:
101     static constexpr uint16_t kSize = 3; ///< Transaction Id size (in bytes).
102 
103     /**
104      * Generates a cryptographically secure random sequence to populate the transaction identifier.
105      *
106      * @retval kErrorNone     Successfully generated a random transaction identifier.
107      * @retval kErrorFailed   Failed to generate random sequence.
108      *
109      */
GenerateRandom(void)110     Error GenerateRandom(void)
111     {
112         OT_UNUSED_VARIABLE(m8);
113 
114         return Random::Crypto::Fill(*this);
115     }
116 
117 private:
118     uint8_t m8[kSize];
119 } OT_TOOL_PACKED_END;
120 
121 /**
122  * Implements DHCPv6 header.
123  *
124  */
125 OT_TOOL_PACKED_BEGIN
126 class Header : public Clearable<Header>
127 {
128 public:
129     /**
130      * Returns the DHCPv6 message type.
131      *
132      * @returns The DHCPv6 message type.
133      *
134      */
GetType(void) const135     Type GetType(void) const { return mType; }
136 
137     /**
138      * Sets the DHCPv6 message type.
139      *
140      * @param[in]  aType  The DHCPv6 message type.
141      *
142      */
SetType(Type aType)143     void SetType(Type aType) { mType = aType; }
144 
145     /**
146      * Returns the DHCPv6 message transaction identifier.
147      *
148      * @returns The DHCPv6 message transaction identifier.
149      *
150      */
GetTransactionId(void) const151     const TransactionId &GetTransactionId(void) const { return mTransactionId; }
152 
153     /**
154      * Sets the DHCPv6 message transaction identifier.
155      *
156      * @param[in]  aTransactionId  The DHCPv6 message transaction identifier.
157      *
158      */
SetTransactionId(const TransactionId & aTransactionId)159     void SetTransactionId(const TransactionId &aTransactionId) { mTransactionId = aTransactionId; }
160 
161 private:
162     Type          mType;
163     TransactionId mTransactionId;
164 } OT_TOOL_PACKED_END;
165 
166 /**
167  * DHCPv6 Option Codes.
168  *
169  */
170 enum Code : uint16_t
171 {
172     kOptionClientIdentifier          = 1,
173     kOptionServerIdentifier          = 2,
174     kOptionIaNa                      = 3,
175     kOptionIaTa                      = 4,
176     kOptionIaAddress                 = 5,
177     kOptionRequestOption             = 6,
178     kOptionPreference                = 7,
179     kOptionElapsedTime               = 8,
180     kOptionRelayMessage              = 9,
181     kOptionAuthentication            = 11,
182     kOptionServerUnicast             = 12,
183     kOptionStatusCode                = 13,
184     kOptionRapidCommit               = 14,
185     kOptionUserClass                 = 15,
186     kOptionVendorClass               = 16,
187     kOptionVendorSpecificInformation = 17,
188     kOptionInterfaceId               = 18,
189     kOptionReconfigureMessage        = 19,
190     kOptionReconfigureAccept         = 20,
191     kOptionLeaseQuery                = 44,
192     kOptionClientData                = 45,
193     kOptionClientLastTransactionTime = 46,
194 };
195 
196 /**
197  * Implements DHCPv6 option.
198  *
199  */
200 OT_TOOL_PACKED_BEGIN
201 class Option
202 {
203 public:
204     /**
205      * Initializes the DHCPv6 option to all zeros.
206      *
207      */
Init(void)208     void Init(void)
209     {
210         mCode   = 0;
211         mLength = 0;
212     }
213 
214     /**
215      * Returns the DHCPv6 option code.
216      *
217      * @returns The DHCPv6 option code.
218      *
219      */
GetCode(void) const220     Code GetCode(void) const { return static_cast<Code>(HostSwap16(mCode)); }
221 
222     /**
223      * Sets the DHCPv6 option code.
224      *
225      * @param[in]  aCode  The DHCPv6 option code.
226      *
227      */
SetCode(Code aCode)228     void SetCode(Code aCode) { mCode = HostSwap16(static_cast<uint16_t>(aCode)); }
229 
230     /**
231      * Returns the length of DHCPv6 option.
232      *
233      * @returns The length of DHCPv6 option.
234      *
235      */
GetLength(void) const236     uint16_t GetLength(void) const { return HostSwap16(mLength); }
237 
238     /**
239      * Sets the length of DHCPv6 option.
240      *
241      * @param[in]  aLength  The length of DHCPv6 option.
242      *
243      */
SetLength(uint16_t aLength)244     void SetLength(uint16_t aLength) { mLength = HostSwap16(aLength); }
245 
246 private:
247     uint16_t mCode;
248     uint16_t mLength;
249 } OT_TOOL_PACKED_END;
250 
251 /**
252  * DHCP6 Unique Identifier (DUID) Type.
253  *
254  */
255 enum DuidType : uint16_t
256 {
257     kDuidLinkLayerAddressPlusTime = 1, ///< Link-layer address plus time (DUID-LLT).
258     kDuidEnterpriseNumber         = 2, ///< Vendor-assigned unique ID based on Enterprise Number (DUID-EN).
259     kDuidLinkLayerAddress         = 3, ///< Link-layer address (DUID-LL).
260 };
261 
262 OT_TOOL_PACKED_BEGIN
263 class ClientIdentifier : public Option
264 {
265 public:
266     /**
267      * Initializes the DHCPv6 Option.
268      *
269      */
Init(void)270     void Init(void)
271     {
272         SetCode(kOptionClientIdentifier);
273         SetLength(sizeof(*this) - sizeof(Option));
274     }
275 
276     /**
277      * Returns the client DUID Type.
278      *
279      * @returns The client DUID Type.
280      *
281      */
GetDuidType(void) const282     DuidType GetDuidType(void) const { return static_cast<DuidType>(HostSwap16(mDuidType)); }
283 
284     /**
285      * Sets the client DUID Type.
286      *
287      * @param[in]  aDuidType  The client DUID Type.
288      *
289      */
SetDuidType(DuidType aDuidType)290     void SetDuidType(DuidType aDuidType) { mDuidType = HostSwap16(static_cast<uint16_t>(aDuidType)); }
291 
292     /**
293      * Returns the client Duid HardwareType.
294      *
295      * @returns The client Duid HardwareType.
296      *
297      */
GetDuidHardwareType(void) const298     uint16_t GetDuidHardwareType(void) const { return HostSwap16(mDuidHardwareType); }
299 
300     /**
301      * Sets the client Duid HardwareType.
302      *
303      * @param[in]  aDuidHardwareType  The client Duid HardwareType.
304      *
305      */
SetDuidHardwareType(uint16_t aDuidHardwareType)306     void SetDuidHardwareType(uint16_t aDuidHardwareType) { mDuidHardwareType = HostSwap16(aDuidHardwareType); }
307 
308     /**
309      * Returns the client LinkLayerAddress.
310      *
311      * @returns The link-layer address.
312      *
313      */
GetDuidLinkLayerAddress(void) const314     const Mac::ExtAddress &GetDuidLinkLayerAddress(void) const { return mDuidLinkLayerAddress; }
315 
316     /**
317      * Sets the client LinkLayerAddress.
318      *
319      * @param[in]  aDuidLinkLayerAddress  The client LinkLayerAddress.
320      *
321      */
SetDuidLinkLayerAddress(const Mac::ExtAddress & aDuidLinkLayerAddress)322     void SetDuidLinkLayerAddress(const Mac::ExtAddress &aDuidLinkLayerAddress)
323     {
324         mDuidLinkLayerAddress = aDuidLinkLayerAddress;
325     }
326 
327 private:
328     uint16_t        mDuidType;
329     uint16_t        mDuidHardwareType;
330     Mac::ExtAddress mDuidLinkLayerAddress;
331 } OT_TOOL_PACKED_END;
332 
333 OT_TOOL_PACKED_BEGIN
334 class ServerIdentifier : public Option
335 {
336 public:
337     /**
338      * Initializes the DHCPv6 Option.
339      *
340      */
Init(void)341     void Init(void)
342     {
343         SetCode(kOptionServerIdentifier);
344         SetLength(sizeof(*this) - sizeof(Option));
345     }
346 
347     /**
348      * Returns the server DUID Type.
349      *
350      * @returns The server DUID Type.
351      *
352      */
GetDuidType(void) const353     DuidType GetDuidType(void) const { return static_cast<DuidType>(HostSwap16(mDuidType)); }
354 
355     /**
356      * Sets the server DUID Type.
357      *
358      * @param[in]  aDuidType  The server DUID Type.
359      *
360      */
SetDuidType(DuidType aDuidType)361     void SetDuidType(DuidType aDuidType) { mDuidType = HostSwap16(static_cast<uint16_t>(aDuidType)); }
362 
363     /**
364      * Returns the server DUID HardwareType.
365      *
366      * @returns The server DUID HardwareType.
367      *
368      */
GetDuidHardwareType(void) const369     uint16_t GetDuidHardwareType(void) const { return HostSwap16(mDuidHardwareType); }
370 
371     /**
372      * Sets the server DUID HardwareType.
373      *
374      * @param[in]  aDuidHardwareType  The server DUID HardwareType.
375      *
376      */
SetDuidHardwareType(uint16_t aDuidHardwareType)377     void SetDuidHardwareType(uint16_t aDuidHardwareType) { mDuidHardwareType = HostSwap16(aDuidHardwareType); }
378 
379     /**
380      * Returns the server LinkLayerAddress.
381      *
382      * @returns The link-layer address.
383      *
384      */
GetDuidLinkLayerAddress(void) const385     const Mac::ExtAddress &GetDuidLinkLayerAddress(void) const { return mDuidLinkLayerAddress; }
386 
387     /**
388      * Sets the server LinkLayerAddress.
389      *
390      * @param[in]  aDuidLinkLayerAddress  The server LinkLayerAddress.
391      *
392      */
SetDuidLinkLayerAddress(const Mac::ExtAddress & aDuidLinkLayerAddress)393     void SetDuidLinkLayerAddress(const Mac::ExtAddress &aDuidLinkLayerAddress)
394     {
395         mDuidLinkLayerAddress = aDuidLinkLayerAddress;
396     }
397 
398 private:
399     uint16_t        mDuidType;
400     uint16_t        mDuidHardwareType;
401     Mac::ExtAddress mDuidLinkLayerAddress;
402 } OT_TOOL_PACKED_END;
403 
404 /**
405  * Represents an Identity Association for Non-temporary Address DHCPv6 option.
406  *
407  */
408 OT_TOOL_PACKED_BEGIN
409 class IaNa : public Option
410 {
411 public:
412     static constexpr uint32_t kDefaultT1 = 0xffffffffU; ///< Default T1 value.
413     static constexpr uint32_t kDefaultT2 = 0xffffffffU; ///< Default T2 value.
414 
415     /**
416      * Initializes the DHCPv6 Option.
417      *
418      */
Init(void)419     void Init(void)
420     {
421         SetCode(kOptionIaNa);
422         SetLength(sizeof(*this) - sizeof(Option));
423     }
424 
425     /**
426      * Returns client IAID.
427      *
428      * @returns The client IAID.
429      *
430      */
GetIaid(void) const431     uint32_t GetIaid(void) const { return HostSwap32(mIaid); }
432 
433     /**
434      * Sets the client IAID.
435      *
436      * @param[in]  aIaid  The client IAID.
437      *
438      */
SetIaid(uint32_t aIaid)439     void SetIaid(uint32_t aIaid) { mIaid = HostSwap32(aIaid); }
440 
441     /**
442      * Returns T1.
443      *
444      * @returns The value of T1.
445      *
446      */
GetT1(void) const447     uint32_t GetT1(void) const { return HostSwap32(mT1); }
448 
449     /**
450      * Sets the value of T1.
451      *
452      * @param[in]  aT1  The value of T1.
453      *
454      */
SetT1(uint32_t aT1)455     void SetT1(uint32_t aT1) { mT1 = HostSwap32(aT1); }
456 
457     /**
458      * Returns T2.
459      *
460      * @returns The value of T2.
461      *
462      */
GetT2(void) const463     uint32_t GetT2(void) const { return HostSwap32(mT2); }
464 
465     /**
466      * Sets the value of T2.
467      *
468      * @param[in]  aT2  The value of T2.
469      *
470      */
SetT2(uint32_t aT2)471     void SetT2(uint32_t aT2) { mT2 = HostSwap32(aT2); }
472 
473 private:
474     uint32_t mIaid;
475     uint32_t mT1;
476     uint32_t mT2;
477 } OT_TOOL_PACKED_END;
478 
479 /**
480  * Represents an Identity Association Address DHCPv6 option.
481  *
482  */
483 OT_TOOL_PACKED_BEGIN
484 class IaAddress : public Option
485 {
486 public:
487     static constexpr uint32_t kDefaultPreferredLifetime = 0xffffffffU; ///< Default preferred lifetime.
488     static constexpr uint32_t kDefaultValidLifetime     = 0xffffffffU; ///< Default valid lifetime.
489 
490     /**
491      * Initializes the DHCPv6 Option.
492      *
493      */
Init(void)494     void Init(void)
495     {
496         SetCode(kOptionIaAddress);
497         SetLength(sizeof(*this) - sizeof(Option));
498     }
499 
500     /**
501      * Returns a reference to the IPv6 address.
502      *
503      * @returns A reference to the IPv6 address.
504      *
505      */
GetAddress(void)506     Ip6::Address &GetAddress(void) { return mAddress; }
507 
508     /**
509      * Returns a reference to the IPv6 address.
510      *
511      * @returns A reference to the IPv6 address.
512      *
513      */
GetAddress(void) const514     const Ip6::Address &GetAddress(void) const { return mAddress; }
515 
516     /**
517      * Sets the IPv6 address.
518      *
519      * @param[in]  aAddress  The reference to the IPv6 address to set.
520      *
521      */
SetAddress(const Ip6::Address & aAddress)522     void SetAddress(const Ip6::Address &aAddress) { mAddress = aAddress; }
523 
524     /**
525      * Returns the preferred lifetime of the IPv6 address.
526      *
527      * @returns The preferred lifetime of the IPv6 address.
528      *
529      */
GetPreferredLifetime(void) const530     uint32_t GetPreferredLifetime(void) const { return HostSwap32(mPreferredLifetime); }
531 
532     /**
533      * Sets the preferred lifetime of the IPv6 address.
534      *
535      * @param[in]  aPreferredLifetime  The preferred lifetime of the IPv6 address.
536      *
537      */
SetPreferredLifetime(uint32_t aPreferredLifetime)538     void SetPreferredLifetime(uint32_t aPreferredLifetime) { mPreferredLifetime = HostSwap32(aPreferredLifetime); }
539 
540     /**
541      * Returns the valid lifetime of the IPv6 address.
542      *
543      * @returns The valid lifetime of the IPv6 address.
544      *
545      */
GetValidLifetime(void) const546     uint32_t GetValidLifetime(void) const { return HostSwap32(mValidLifetime); }
547 
548     /**
549      * Sets the valid lifetime of the IPv6 address.
550      *
551      * @param[in]  aValidLifetime  The valid lifetime of the IPv6 address.
552      *
553      */
SetValidLifetime(uint32_t aValidLifetime)554     void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = HostSwap32(aValidLifetime); }
555 
556 private:
557     Ip6::Address mAddress;
558     uint32_t     mPreferredLifetime;
559     uint32_t     mValidLifetime;
560 } OT_TOOL_PACKED_END;
561 
562 /**
563  * Represents an Elapsed Time DHCPv6 option.
564  *
565  */
566 OT_TOOL_PACKED_BEGIN
567 class ElapsedTime : public Option
568 {
569 public:
570     /**
571      * Initializes the DHCPv6 Option.
572      *
573      */
Init(void)574     void Init(void)
575     {
576         SetCode(kOptionElapsedTime);
577         SetLength(sizeof(*this) - sizeof(Option));
578     }
579 
580     /**
581      * Returns the elapsed time since solicit starts.
582      *
583      * @returns The elapsed time since solicit starts.
584      *
585      */
GetElapsedTime(void) const586     uint16_t GetElapsedTime(void) const { return HostSwap16(mElapsedTime); }
587 
588     /**
589      * Sets the elapsed time since solicit starts.
590      *
591      * @param[in] aElapsedTime The elapsed time since solicit starts.
592      *
593      */
SetElapsedTime(uint16_t aElapsedTime)594     void SetElapsedTime(uint16_t aElapsedTime) { mElapsedTime = HostSwap16(aElapsedTime); }
595 
596 private:
597     uint16_t mElapsedTime;
598 } OT_TOOL_PACKED_END;
599 
600 /**
601  * Status Code.
602  *
603  */
604 enum Status : uint16_t
605 {
606     kStatusSuccess      = 0,
607     kStatusUnspecFail   = 1,
608     kStatusNoAddrsAvail = 2,
609     kStatusNoBinding    = 3,
610     kStatusNotOnLink    = 4,
611     kStatusUseMulticast = 5,
612     kUnknownQueryType   = 7,
613     kMalformedQuery     = 8,
614     kNotConfigured      = 9,
615     kNotAllowed         = 10,
616 };
617 
618 /**
619  * Represents an Status Code DHCPv6 option.
620  *
621  */
622 OT_TOOL_PACKED_BEGIN
623 class StatusCode : public Option
624 {
625 public:
626     /**
627      * Initializes the DHCPv6 Option.
628      *
629      */
Init(void)630     void Init(void)
631     {
632         SetCode(kOptionStatusCode);
633         SetLength(sizeof(*this) - sizeof(Option));
634     }
635 
636     /**
637      * Returns the status code.
638      *
639      * @returns The status code.
640      *
641      */
GetStatusCode(void) const642     Status GetStatusCode(void) const { return static_cast<Status>(HostSwap16(mStatus)); }
643 
644     /**
645      * Sets the status code.
646      *
647      * @param[in] aStatus The status code.
648      *
649      */
SetStatusCode(Status aStatus)650     void SetStatusCode(Status aStatus) { mStatus = HostSwap16(static_cast<uint16_t>(aStatus)); }
651 
652 private:
653     uint16_t mStatus;
654 } OT_TOOL_PACKED_END;
655 
656 /**
657  * Represents an Rapid Commit DHCPv6 option.
658  *
659  */
660 OT_TOOL_PACKED_BEGIN
661 class RapidCommit : public Option
662 {
663 public:
664     /**
665      * Initializes the DHCPv6 Option.
666      *
667      */
Init(void)668     void Init(void)
669     {
670         SetCode(kOptionRapidCommit);
671         SetLength(sizeof(*this) - sizeof(Option));
672     }
673 } OT_TOOL_PACKED_END;
674 
675 } // namespace Dhcp6
676 } // namespace ot
677 
678 #endif // #if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE || OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
679 
680 #endif // DHCP6_HPP_
681