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  * This class 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      * This method 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) { return Random::Crypto::FillBuffer(m8, kSize); }
111 
112 private:
113     uint8_t m8[kSize];
114 } OT_TOOL_PACKED_END;
115 
116 /**
117  * This class implements DHCPv6 header.
118  *
119  */
120 OT_TOOL_PACKED_BEGIN
121 class Header : public Clearable<Header>
122 {
123 public:
124     /**
125      * This method returns the DHCPv6 message type.
126      *
127      * @returns The DHCPv6 message type.
128      *
129      */
GetType(void) const130     Type GetType(void) const { return mType; }
131 
132     /**
133      * This method sets the DHCPv6 message type.
134      *
135      * @param[in]  aType  The DHCPv6 message type.
136      *
137      */
SetType(Type aType)138     void SetType(Type aType) { mType = aType; }
139 
140     /**
141      * This method returns the DHCPv6 message transaction identifier.
142      *
143      * @returns The DHCPv6 message transaction identifier.
144      *
145      */
GetTransactionId(void) const146     const TransactionId &GetTransactionId(void) const { return mTransactionId; }
147 
148     /**
149      * This method sets the DHCPv6 message transaction identifier.
150      *
151      * @param[in]  aTransactionId  The DHCPv6 message transaction identifier.
152      *
153      */
SetTransactionId(const TransactionId & aTransactionId)154     void SetTransactionId(const TransactionId &aTransactionId) { mTransactionId = aTransactionId; }
155 
156 private:
157     Type          mType;
158     TransactionId mTransactionId;
159 } OT_TOOL_PACKED_END;
160 
161 /**
162  * DHCPv6 Option Codes.
163  *
164  */
165 enum Code : uint16_t
166 {
167     kOptionClientIdentifier          = 1,
168     kOptionServerIdentifier          = 2,
169     kOptionIaNa                      = 3,
170     kOptionIaTa                      = 4,
171     kOptionIaAddress                 = 5,
172     kOptionRequestOption             = 6,
173     kOptionPreference                = 7,
174     kOptionElapsedTime               = 8,
175     kOptionRelayMessage              = 9,
176     kOptionAuthentication            = 11,
177     kOptionServerUnicast             = 12,
178     kOptionStatusCode                = 13,
179     kOptionRapidCommit               = 14,
180     kOptionUserClass                 = 15,
181     kOptionVendorClass               = 16,
182     kOptionVendorSpecificInformation = 17,
183     kOptionInterfaceId               = 18,
184     kOptionReconfigureMessage        = 19,
185     kOptionReconfigureAccept         = 20,
186     kOptionLeaseQuery                = 44,
187     kOptionClientData                = 45,
188     kOptionClientLastTransactionTime = 46,
189 };
190 
191 /**
192  * This class implements DHCPv6 option.
193  *
194  */
195 OT_TOOL_PACKED_BEGIN
196 class Option
197 {
198 public:
199     /**
200      * This method initializes the DHCPv6 option to all zeros.
201      *
202      */
Init(void)203     void Init(void)
204     {
205         mCode   = 0;
206         mLength = 0;
207     }
208 
209     /**
210      * This method returns the DHCPv6 option code.
211      *
212      * @returns The DHCPv6 option code.
213      *
214      */
GetCode(void) const215     Code GetCode(void) const { return static_cast<Code>(HostSwap16(mCode)); }
216 
217     /**
218      * This method sets the DHCPv6 option code.
219      *
220      * @param[in]  aCode  The DHCPv6 option code.
221      *
222      */
SetCode(Code aCode)223     void SetCode(Code aCode) { mCode = HostSwap16(static_cast<uint16_t>(aCode)); }
224 
225     /**
226      * This method returns the length of DHCPv6 option.
227      *
228      * @returns The length of DHCPv6 option.
229      *
230      */
GetLength(void) const231     uint16_t GetLength(void) const { return HostSwap16(mLength); }
232 
233     /**
234      * This method sets the length of DHCPv6 option.
235      *
236      * @param[in]  aLength  The length of DHCPv6 option.
237      *
238      */
SetLength(uint16_t aLength)239     void SetLength(uint16_t aLength) { mLength = HostSwap16(aLength); }
240 
241 private:
242     uint16_t mCode;
243     uint16_t mLength;
244 } OT_TOOL_PACKED_END;
245 
246 /**
247  * DHCP6 Unique Identifier (DUID) Type.
248  *
249  */
250 enum DuidType : uint16_t
251 {
252     kDuidLinkLayerAddressPlusTime = 1, ///< Link-layer address plus time (DUID-LLT).
253     kDuidEnterpriseNumber         = 2, ///< Vendor-assigned unique ID based on Enterprise Number (DUID-EN).
254     kDuidLinkLayerAddress         = 3, ///< Link-layer address (DUID-LL).
255 };
256 
257 OT_TOOL_PACKED_BEGIN
258 class ClientIdentifier : public Option
259 {
260 public:
261     /**
262      * This method initializes the DHCPv6 Option.
263      *
264      */
Init(void)265     void Init(void)
266     {
267         SetCode(kOptionClientIdentifier);
268         SetLength(sizeof(*this) - sizeof(Option));
269     }
270 
271     /**
272      * This method returns the client DUID Type.
273      *
274      * @returns The client DUID Type.
275      *
276      */
GetDuidType(void) const277     DuidType GetDuidType(void) const { return static_cast<DuidType>(HostSwap16(mDuidType)); }
278 
279     /**
280      * This method sets the client DUID Type.
281      *
282      * @param[in]  aDuidType  The client DUID Type.
283      *
284      */
SetDuidType(DuidType aDuidType)285     void SetDuidType(DuidType aDuidType) { mDuidType = HostSwap16(static_cast<uint16_t>(aDuidType)); }
286 
287     /**
288      * This method returns the client Duid HardwareType.
289      *
290      * @returns The client Duid HardwareType.
291      *
292      */
GetDuidHardwareType(void) const293     uint16_t GetDuidHardwareType(void) const { return HostSwap16(mDuidHardwareType); }
294 
295     /**
296      * This method sets the client Duid HardwareType.
297      *
298      * @param[in]  aDuidHardwareType  The client Duid HardwareType.
299      *
300      */
SetDuidHardwareType(uint16_t aDuidHardwareType)301     void SetDuidHardwareType(uint16_t aDuidHardwareType) { mDuidHardwareType = HostSwap16(aDuidHardwareType); }
302 
303     /**
304      * This method returns the client LinkLayerAddress.
305      *
306      * @returns The link-layer address.
307      *
308      */
GetDuidLinkLayerAddress(void) const309     const Mac::ExtAddress &GetDuidLinkLayerAddress(void) const { return mDuidLinkLayerAddress; }
310 
311     /**
312      * This method sets the client LinkLayerAddress.
313      *
314      * @param[in]  aDuidLinkLayerAddress  The client LinkLayerAddress.
315      *
316      */
SetDuidLinkLayerAddress(const Mac::ExtAddress & aDuidLinkLayerAddress)317     void SetDuidLinkLayerAddress(const Mac::ExtAddress &aDuidLinkLayerAddress)
318     {
319         mDuidLinkLayerAddress = aDuidLinkLayerAddress;
320     }
321 
322 private:
323     uint16_t        mDuidType;
324     uint16_t        mDuidHardwareType;
325     Mac::ExtAddress mDuidLinkLayerAddress;
326 } OT_TOOL_PACKED_END;
327 
328 OT_TOOL_PACKED_BEGIN
329 class ServerIdentifier : public Option
330 {
331 public:
332     /**
333      * This method initializes the DHCPv6 Option.
334      *
335      */
Init(void)336     void Init(void)
337     {
338         SetCode(kOptionServerIdentifier);
339         SetLength(sizeof(*this) - sizeof(Option));
340     }
341 
342     /**
343      * This method returns the server DUID Type.
344      *
345      * @returns The server DUID Type.
346      *
347      */
GetDuidType(void) const348     DuidType GetDuidType(void) const { return static_cast<DuidType>(HostSwap16(mDuidType)); }
349 
350     /**
351      * This method sets the server DUID Type.
352      *
353      * @param[in]  aDuidType  The server DUID Type.
354      *
355      */
SetDuidType(DuidType aDuidType)356     void SetDuidType(DuidType aDuidType) { mDuidType = HostSwap16(static_cast<uint16_t>(aDuidType)); }
357 
358     /**
359      * This method returns the server DUID HardwareType.
360      *
361      * @returns The server DUID HardwareType.
362      *
363      */
GetDuidHardwareType(void) const364     uint16_t GetDuidHardwareType(void) const { return HostSwap16(mDuidHardwareType); }
365 
366     /**
367      * This method sets the server DUID HardwareType.
368      *
369      * @param[in]  aDuidHardwareType  The server DUID HardwareType.
370      *
371      */
SetDuidHardwareType(uint16_t aDuidHardwareType)372     void SetDuidHardwareType(uint16_t aDuidHardwareType) { mDuidHardwareType = HostSwap16(aDuidHardwareType); }
373 
374     /**
375      * This method returns the server LinkLayerAddress.
376      *
377      * @returns The link-layer address.
378      *
379      */
GetDuidLinkLayerAddress(void) const380     const Mac::ExtAddress &GetDuidLinkLayerAddress(void) const { return mDuidLinkLayerAddress; }
381 
382     /**
383      * This method sets the server LinkLayerAddress.
384      *
385      * @param[in]  aDuidLinkLayerAddress  The server LinkLayerAddress.
386      *
387      */
SetDuidLinkLayerAddress(const Mac::ExtAddress & aDuidLinkLayerAddress)388     void SetDuidLinkLayerAddress(const Mac::ExtAddress &aDuidLinkLayerAddress)
389     {
390         mDuidLinkLayerAddress = aDuidLinkLayerAddress;
391     }
392 
393 private:
394     uint16_t        mDuidType;
395     uint16_t        mDuidHardwareType;
396     Mac::ExtAddress mDuidLinkLayerAddress;
397 } OT_TOOL_PACKED_END;
398 
399 /**
400  * This type represents an Identity Association for Non-temporary Address DHCPv6 option.
401  *
402  */
403 OT_TOOL_PACKED_BEGIN
404 class IaNa : public Option
405 {
406 public:
407     static constexpr uint32_t kDefaultT1 = 0xffffffffU; ///< Default T1 value.
408     static constexpr uint32_t kDefaultT2 = 0xffffffffU; ///< Default T2 value.
409 
410     /**
411      * This method initializes the DHCPv6 Option.
412      *
413      */
Init(void)414     void Init(void)
415     {
416         SetCode(kOptionIaNa);
417         SetLength(sizeof(*this) - sizeof(Option));
418     }
419 
420     /**
421      * This method returns client IAID.
422      *
423      * @returns The client IAID.
424      *
425      */
GetIaid(void) const426     uint32_t GetIaid(void) const { return HostSwap32(mIaid); }
427 
428     /**
429      * This method sets the client IAID.
430      *
431      * @param[in]  aIaid  The client IAID.
432      *
433      */
SetIaid(uint32_t aIaid)434     void SetIaid(uint32_t aIaid) { mIaid = HostSwap32(aIaid); }
435 
436     /**
437      * This method returns T1.
438      *
439      * @returns The value of T1.
440      *
441      */
GetT1(void) const442     uint32_t GetT1(void) const { return HostSwap32(mT1); }
443 
444     /**
445      * This method sets the value of T1.
446      *
447      * @param[in]  aT1  The value of T1.
448      *
449      */
SetT1(uint32_t aT1)450     void SetT1(uint32_t aT1) { mT1 = HostSwap32(aT1); }
451 
452     /**
453      * This method returns T2.
454      *
455      * @returns The value of T2.
456      *
457      */
GetT2(void) const458     uint32_t GetT2(void) const { return HostSwap32(mT2); }
459 
460     /**
461      * This method sets the value of T2.
462      *
463      * @param[in]  aT2  The value of T2.
464      *
465      */
SetT2(uint32_t aT2)466     void SetT2(uint32_t aT2) { mT2 = HostSwap32(aT2); }
467 
468 private:
469     uint32_t mIaid;
470     uint32_t mT1;
471     uint32_t mT2;
472 } OT_TOOL_PACKED_END;
473 
474 /**
475  * This type represents an Identity Association Address DHCPv6 option.
476  *
477  */
478 OT_TOOL_PACKED_BEGIN
479 class IaAddress : public Option
480 {
481 public:
482     static constexpr uint32_t kDefaultPreferredLifetime = 0xffffffffU; ///< Default preferred lifetime.
483     static constexpr uint32_t kDefaultValidLifetime     = 0xffffffffU; ///< Default valid lifetime.
484 
485     /**
486      * This method initializes the DHCPv6 Option.
487      *
488      */
Init(void)489     void Init(void)
490     {
491         SetCode(kOptionIaAddress);
492         SetLength(sizeof(*this) - sizeof(Option));
493     }
494 
495     /**
496      * This method returns a reference to the IPv6 address.
497      *
498      * @returns A reference to the IPv6 address.
499      *
500      */
GetAddress(void)501     Ip6::Address &GetAddress(void) { return mAddress; }
502 
503     /**
504      * This method returns a reference to the IPv6 address.
505      *
506      * @returns A reference to the IPv6 address.
507      *
508      */
GetAddress(void) const509     const Ip6::Address &GetAddress(void) const { return mAddress; }
510 
511     /**
512      * This method sets the IPv6 address.
513      *
514      * @param[in]  aAddress  The reference to the IPv6 address to set.
515      *
516      */
SetAddress(const Ip6::Address & aAddress)517     void SetAddress(const Ip6::Address &aAddress) { mAddress = aAddress; }
518 
519     /**
520      * This method returns the preferred lifetime of the IPv6 address.
521      *
522      * @returns The preferred lifetime of the IPv6 address.
523      *
524      */
GetPreferredLifetime(void) const525     uint32_t GetPreferredLifetime(void) const { return HostSwap32(mPreferredLifetime); }
526 
527     /**
528      * This method sets the preferred lifetime of the IPv6 address.
529      *
530      * @param[in]  aPreferredLifetime  The preferred lifetime of the IPv6 address.
531      *
532      */
SetPreferredLifetime(uint32_t aPreferredLifetime)533     void SetPreferredLifetime(uint32_t aPreferredLifetime) { mPreferredLifetime = HostSwap32(aPreferredLifetime); }
534 
535     /**
536      * This method returns the valid lifetime of the IPv6 address.
537      *
538      * @returns The valid lifetime of the IPv6 address.
539      *
540      */
GetValidLifetime(void) const541     uint32_t GetValidLifetime(void) const { return HostSwap32(mValidLifetime); }
542 
543     /**
544      * This method sets the valid lifetime of the IPv6 address.
545      *
546      * @param[in]  aValidLifetime  The valid lifetime of the IPv6 address.
547      *
548      */
SetValidLifetime(uint32_t aValidLifetime)549     void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = HostSwap32(aValidLifetime); }
550 
551 private:
552     Ip6::Address mAddress;
553     uint32_t     mPreferredLifetime;
554     uint32_t     mValidLifetime;
555 } OT_TOOL_PACKED_END;
556 
557 /**
558  * This type represents an Elapsed Time DHCPv6 option.
559  *
560  */
561 OT_TOOL_PACKED_BEGIN
562 class ElapsedTime : public Option
563 {
564 public:
565     /**
566      * This method initializes the DHCPv6 Option.
567      *
568      */
Init(void)569     void Init(void)
570     {
571         SetCode(kOptionElapsedTime);
572         SetLength(sizeof(*this) - sizeof(Option));
573     }
574 
575     /**
576      * This method returns the elapsed time since solicit starts.
577      *
578      * @returns The elapsed time since solicit starts.
579      *
580      */
GetElapsedTime(void) const581     uint16_t GetElapsedTime(void) const { return HostSwap16(mElapsedTime); }
582 
583     /**
584      * This method sets the elapsed time since solicit starts.
585      *
586      * @param[in] aElapsedTime The elapsed time since solicit starts.
587      *
588      */
SetElapsedTime(uint16_t aElapsedTime)589     void SetElapsedTime(uint16_t aElapsedTime) { mElapsedTime = HostSwap16(aElapsedTime); }
590 
591 private:
592     uint16_t mElapsedTime;
593 } OT_TOOL_PACKED_END;
594 
595 /**
596  * Status Code.
597  *
598  */
599 enum Status : uint16_t
600 {
601     kStatusSuccess      = 0,
602     kStatusUnspecFail   = 1,
603     kStatusNoAddrsAvail = 2,
604     kStatusNoBinding    = 3,
605     kStatusNotOnLink    = 4,
606     kStatusUseMulticast = 5,
607     kUnknownQueryType   = 7,
608     kMalformedQuery     = 8,
609     kNotConfigured      = 9,
610     kNotAllowed         = 10,
611 };
612 
613 /**
614  * This type represents an Status Code DHCPv6 option.
615  *
616  */
617 OT_TOOL_PACKED_BEGIN
618 class StatusCode : public Option
619 {
620 public:
621     /**
622      * This method initializes the DHCPv6 Option.
623      *
624      */
Init(void)625     void Init(void)
626     {
627         SetCode(kOptionStatusCode);
628         SetLength(sizeof(*this) - sizeof(Option));
629     }
630 
631     /**
632      * This method returns the status code.
633      *
634      * @returns The status code.
635      *
636      */
GetStatusCode(void) const637     Status GetStatusCode(void) const { return static_cast<Status>(HostSwap16(mStatus)); }
638 
639     /**
640      * This method sets the status code.
641      *
642      * @param[in] aStatus The status code.
643      *
644      */
SetStatusCode(Status aStatus)645     void SetStatusCode(Status aStatus) { mStatus = HostSwap16(static_cast<uint16_t>(aStatus)); }
646 
647 private:
648     uint16_t mStatus;
649 } OT_TOOL_PACKED_END;
650 
651 /**
652  * This type represents an Rapid Commit DHCPv6 option.
653  *
654  */
655 OT_TOOL_PACKED_BEGIN
656 class RapidCommit : public Option
657 {
658 public:
659     /**
660      * This method initializes the DHCPv6 Option.
661      *
662      */
Init(void)663     void Init(void)
664     {
665         SetCode(kOptionRapidCommit);
666         SetLength(sizeof(*this) - sizeof(Option));
667     }
668 } OT_TOOL_PACKED_END;
669 
670 } // namespace Dhcp6
671 } // namespace ot
672 
673 #endif // #if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE || OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
674 
675 #endif // DHCP6_HPP_
676