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 /**
52  * @addtogroup core-dhcp6
53  *
54  * @brief
55  *   This module includes definitions for DHCPv6.
56  *
57  * @{
58  *
59  */
60 
61 constexpr uint16_t kDhcpClientPort       = 546;
62 constexpr uint16_t kDhcpServerPort       = 547;
63 constexpr uint16_t kHardwareTypeEui64    = 27;
64 constexpr uint16_t kHardwareTypeEthernet = 1;
65 
66 /**
67  * DHCPv6 Message Types
68  *
69  */
70 enum Type : uint8_t
71 {
72     kTypeNone               = 0,
73     kTypeSolicit            = 1,
74     kTypeAdvertise          = 2,
75     kTypeRequest            = 3,
76     kTypeConfirm            = 4,
77     kTypeRenew              = 5,
78     kTypeRebind             = 6,
79     kTypeReply              = 7,
80     kTypeRelease            = 8,
81     kTypeDecline            = 9,
82     kTypeReconfigure        = 10,
83     kTypeInformationRequest = 11,
84     kTypeRelayForward       = 12,
85     kTypeRelayReply         = 13,
86     kTypeLeaseQuery         = 14,
87     kTypeLeaseQueryReply    = 15,
88 };
89 
90 /**
91  * Represents a DHCP6 transaction identifier.
92  *
93  */
94 OT_TOOL_PACKED_BEGIN
95 class TransactionId : public Equatable<TransactionId>, public Clearable<TransactionId>
96 {
97 public:
98     static constexpr uint16_t kSize = 3; ///< Transaction Id size (in bytes).
99 
100     /**
101      * Generates a cryptographically secure random sequence to populate the transaction identifier.
102      *
103      * @retval kErrorNone     Successfully generated a random transaction identifier.
104      * @retval kErrorFailed   Failed to generate random sequence.
105      *
106      */
GenerateRandom(void)107     Error GenerateRandom(void)
108     {
109         OT_UNUSED_VARIABLE(m8);
110 
111         return Random::Crypto::Fill(*this);
112     }
113 
114 private:
115     uint8_t m8[kSize];
116 } OT_TOOL_PACKED_END;
117 
118 /**
119  * Implements DHCPv6 header.
120  *
121  */
122 OT_TOOL_PACKED_BEGIN
123 class Header : public Clearable<Header>
124 {
125 public:
126     /**
127      * Returns the DHCPv6 message type.
128      *
129      * @returns The DHCPv6 message type.
130      *
131      */
GetType(void) const132     Type GetType(void) const { return mType; }
133 
134     /**
135      * Sets the DHCPv6 message type.
136      *
137      * @param[in]  aType  The DHCPv6 message type.
138      *
139      */
SetType(Type aType)140     void SetType(Type aType) { mType = aType; }
141 
142     /**
143      * Returns the DHCPv6 message transaction identifier.
144      *
145      * @returns The DHCPv6 message transaction identifier.
146      *
147      */
GetTransactionId(void) const148     const TransactionId &GetTransactionId(void) const { return mTransactionId; }
149 
150     /**
151      * Sets the DHCPv6 message transaction identifier.
152      *
153      * @param[in]  aTransactionId  The DHCPv6 message transaction identifier.
154      *
155      */
SetTransactionId(const TransactionId & aTransactionId)156     void SetTransactionId(const TransactionId &aTransactionId) { mTransactionId = aTransactionId; }
157 
158 private:
159     Type          mType;
160     TransactionId mTransactionId;
161 } OT_TOOL_PACKED_END;
162 
163 /**
164  * DHCPv6 Option Codes.
165  *
166  */
167 enum Code : uint16_t
168 {
169     kOptionClientIdentifier          = 1,
170     kOptionServerIdentifier          = 2,
171     kOptionIaNa                      = 3,
172     kOptionIaTa                      = 4,
173     kOptionIaAddress                 = 5,
174     kOptionRequestOption             = 6,
175     kOptionPreference                = 7,
176     kOptionElapsedTime               = 8,
177     kOptionRelayMessage              = 9,
178     kOptionAuthentication            = 11,
179     kOptionServerUnicast             = 12,
180     kOptionStatusCode                = 13,
181     kOptionRapidCommit               = 14,
182     kOptionUserClass                 = 15,
183     kOptionVendorClass               = 16,
184     kOptionVendorSpecificInformation = 17,
185     kOptionInterfaceId               = 18,
186     kOptionReconfigureMessage        = 19,
187     kOptionReconfigureAccept         = 20,
188     kOptionLeaseQuery                = 44,
189     kOptionClientData                = 45,
190     kOptionClientLastTransactionTime = 46,
191 };
192 
193 /**
194  * Implements DHCPv6 option.
195  *
196  */
197 OT_TOOL_PACKED_BEGIN
198 class Option
199 {
200 public:
201     /**
202      * Initializes the DHCPv6 option to all zeros.
203      *
204      */
Init(void)205     void Init(void)
206     {
207         mCode   = 0;
208         mLength = 0;
209     }
210 
211     /**
212      * Returns the DHCPv6 option code.
213      *
214      * @returns The DHCPv6 option code.
215      *
216      */
GetCode(void) const217     Code GetCode(void) const { return static_cast<Code>(BigEndian::HostSwap16(mCode)); }
218 
219     /**
220      * Sets the DHCPv6 option code.
221      *
222      * @param[in]  aCode  The DHCPv6 option code.
223      *
224      */
SetCode(Code aCode)225     void SetCode(Code aCode) { mCode = BigEndian::HostSwap16(static_cast<uint16_t>(aCode)); }
226 
227     /**
228      * Returns the length of DHCPv6 option.
229      *
230      * @returns The length of DHCPv6 option.
231      *
232      */
GetLength(void) const233     uint16_t GetLength(void) const { return BigEndian::HostSwap16(mLength); }
234 
235     /**
236      * Sets the length of DHCPv6 option.
237      *
238      * @param[in]  aLength  The length of DHCPv6 option.
239      *
240      */
SetLength(uint16_t aLength)241     void SetLength(uint16_t aLength) { mLength = BigEndian::HostSwap16(aLength); }
242 
243 private:
244     uint16_t mCode;
245     uint16_t mLength;
246 } OT_TOOL_PACKED_END;
247 
248 /**
249  * DHCP6 Unique Identifier (DUID) Type.
250  *
251  */
252 enum DuidType : uint16_t
253 {
254     kDuidLinkLayerAddressPlusTime = 1, ///< Link-layer address plus time (DUID-LLT).
255     kDuidEnterpriseNumber         = 2, ///< Vendor-assigned unique ID based on Enterprise Number (DUID-EN).
256     kDuidLinkLayerAddress         = 3, ///< Link-layer address (DUID-LL).
257 };
258 
259 OT_TOOL_PACKED_BEGIN
260 class ClientIdentifier : public Option
261 {
262 public:
263     /**
264      * Initializes the DHCPv6 Option.
265      *
266      */
Init(void)267     void Init(void)
268     {
269         SetCode(kOptionClientIdentifier);
270         SetLength(sizeof(*this) - sizeof(Option));
271     }
272 
273     /**
274      * Returns the client DUID Type.
275      *
276      * @returns The client DUID Type.
277      *
278      */
GetDuidType(void) const279     DuidType GetDuidType(void) const { return static_cast<DuidType>(BigEndian::HostSwap16(mDuidType)); }
280 
281     /**
282      * Sets the client DUID Type.
283      *
284      * @param[in]  aDuidType  The client DUID Type.
285      *
286      */
SetDuidType(DuidType aDuidType)287     void SetDuidType(DuidType aDuidType) { mDuidType = BigEndian::HostSwap16(static_cast<uint16_t>(aDuidType)); }
288 
289     /**
290      * Returns the client Duid HardwareType.
291      *
292      * @returns The client Duid HardwareType.
293      *
294      */
GetDuidHardwareType(void) const295     uint16_t GetDuidHardwareType(void) const { return BigEndian::HostSwap16(mDuidHardwareType); }
296 
297     /**
298      * Sets the client Duid HardwareType.
299      *
300      * @param[in]  aDuidHardwareType  The client Duid HardwareType.
301      *
302      */
SetDuidHardwareType(uint16_t aDuidHardwareType)303     void SetDuidHardwareType(uint16_t aDuidHardwareType)
304     {
305         mDuidHardwareType = BigEndian::HostSwap16(aDuidHardwareType);
306     }
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>(BigEndian::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 = BigEndian::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 BigEndian::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)
378     {
379         mDuidHardwareType = BigEndian::HostSwap16(aDuidHardwareType);
380     }
381 
382     /**
383      * Returns the server LinkLayerAddress.
384      *
385      * @returns The link-layer address.
386      *
387      */
GetDuidLinkLayerAddress(void) const388     const Mac::ExtAddress &GetDuidLinkLayerAddress(void) const { return mDuidLinkLayerAddress; }
389 
390     /**
391      * Sets the server LinkLayerAddress.
392      *
393      * @param[in]  aDuidLinkLayerAddress  The server LinkLayerAddress.
394      *
395      */
SetDuidLinkLayerAddress(const Mac::ExtAddress & aDuidLinkLayerAddress)396     void SetDuidLinkLayerAddress(const Mac::ExtAddress &aDuidLinkLayerAddress)
397     {
398         mDuidLinkLayerAddress = aDuidLinkLayerAddress;
399     }
400 
401 private:
402     uint16_t        mDuidType;
403     uint16_t        mDuidHardwareType;
404     Mac::ExtAddress mDuidLinkLayerAddress;
405 } OT_TOOL_PACKED_END;
406 
407 /**
408  * Represents an Identity Association for Non-temporary Address DHCPv6 option.
409  *
410  */
411 OT_TOOL_PACKED_BEGIN
412 class IaNa : public Option
413 {
414 public:
415     static constexpr uint32_t kDefaultT1 = 0xffffffffU; ///< Default T1 value.
416     static constexpr uint32_t kDefaultT2 = 0xffffffffU; ///< Default T2 value.
417 
418     /**
419      * Initializes the DHCPv6 Option.
420      *
421      */
Init(void)422     void Init(void)
423     {
424         SetCode(kOptionIaNa);
425         SetLength(sizeof(*this) - sizeof(Option));
426     }
427 
428     /**
429      * Returns client IAID.
430      *
431      * @returns The client IAID.
432      *
433      */
GetIaid(void) const434     uint32_t GetIaid(void) const { return BigEndian::HostSwap32(mIaid); }
435 
436     /**
437      * Sets the client IAID.
438      *
439      * @param[in]  aIaid  The client IAID.
440      *
441      */
SetIaid(uint32_t aIaid)442     void SetIaid(uint32_t aIaid) { mIaid = BigEndian::HostSwap32(aIaid); }
443 
444     /**
445      * Returns T1.
446      *
447      * @returns The value of T1.
448      *
449      */
GetT1(void) const450     uint32_t GetT1(void) const { return BigEndian::HostSwap32(mT1); }
451 
452     /**
453      * Sets the value of T1.
454      *
455      * @param[in]  aT1  The value of T1.
456      *
457      */
SetT1(uint32_t aT1)458     void SetT1(uint32_t aT1) { mT1 = BigEndian::HostSwap32(aT1); }
459 
460     /**
461      * Returns T2.
462      *
463      * @returns The value of T2.
464      *
465      */
GetT2(void) const466     uint32_t GetT2(void) const { return BigEndian::HostSwap32(mT2); }
467 
468     /**
469      * Sets the value of T2.
470      *
471      * @param[in]  aT2  The value of T2.
472      *
473      */
SetT2(uint32_t aT2)474     void SetT2(uint32_t aT2) { mT2 = BigEndian::HostSwap32(aT2); }
475 
476 private:
477     uint32_t mIaid;
478     uint32_t mT1;
479     uint32_t mT2;
480 } OT_TOOL_PACKED_END;
481 
482 /**
483  * Represents an Identity Association Address DHCPv6 option.
484  *
485  */
486 OT_TOOL_PACKED_BEGIN
487 class IaAddress : public Option
488 {
489 public:
490     static constexpr uint32_t kDefaultPreferredLifetime = 0xffffffffU; ///< Default preferred lifetime.
491     static constexpr uint32_t kDefaultValidLifetime     = 0xffffffffU; ///< Default valid lifetime.
492 
493     /**
494      * Initializes the DHCPv6 Option.
495      *
496      */
Init(void)497     void Init(void)
498     {
499         SetCode(kOptionIaAddress);
500         SetLength(sizeof(*this) - sizeof(Option));
501     }
502 
503     /**
504      * Returns a reference to the IPv6 address.
505      *
506      * @returns A reference to the IPv6 address.
507      *
508      */
GetAddress(void)509     Ip6::Address &GetAddress(void) { return mAddress; }
510 
511     /**
512      * Returns a reference to the IPv6 address.
513      *
514      * @returns A reference to the IPv6 address.
515      *
516      */
GetAddress(void) const517     const Ip6::Address &GetAddress(void) const { return mAddress; }
518 
519     /**
520      * Sets the IPv6 address.
521      *
522      * @param[in]  aAddress  The reference to the IPv6 address to set.
523      *
524      */
SetAddress(const Ip6::Address & aAddress)525     void SetAddress(const Ip6::Address &aAddress) { mAddress = aAddress; }
526 
527     /**
528      * Returns the preferred lifetime of the IPv6 address.
529      *
530      * @returns The preferred lifetime of the IPv6 address.
531      *
532      */
GetPreferredLifetime(void) const533     uint32_t GetPreferredLifetime(void) const { return BigEndian::HostSwap32(mPreferredLifetime); }
534 
535     /**
536      * Sets the preferred lifetime of the IPv6 address.
537      *
538      * @param[in]  aPreferredLifetime  The preferred lifetime of the IPv6 address.
539      *
540      */
SetPreferredLifetime(uint32_t aPreferredLifetime)541     void SetPreferredLifetime(uint32_t aPreferredLifetime)
542     {
543         mPreferredLifetime = BigEndian::HostSwap32(aPreferredLifetime);
544     }
545 
546     /**
547      * Returns the valid lifetime of the IPv6 address.
548      *
549      * @returns The valid lifetime of the IPv6 address.
550      *
551      */
GetValidLifetime(void) const552     uint32_t GetValidLifetime(void) const { return BigEndian::HostSwap32(mValidLifetime); }
553 
554     /**
555      * Sets the valid lifetime of the IPv6 address.
556      *
557      * @param[in]  aValidLifetime  The valid lifetime of the IPv6 address.
558      *
559      */
SetValidLifetime(uint32_t aValidLifetime)560     void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = BigEndian::HostSwap32(aValidLifetime); }
561 
562 private:
563     Ip6::Address mAddress;
564     uint32_t     mPreferredLifetime;
565     uint32_t     mValidLifetime;
566 } OT_TOOL_PACKED_END;
567 
568 /**
569  * Represents an Elapsed Time DHCPv6 option.
570  *
571  */
572 OT_TOOL_PACKED_BEGIN
573 class ElapsedTime : public Option
574 {
575 public:
576     /**
577      * Initializes the DHCPv6 Option.
578      *
579      */
Init(void)580     void Init(void)
581     {
582         SetCode(kOptionElapsedTime);
583         SetLength(sizeof(*this) - sizeof(Option));
584     }
585 
586     /**
587      * Returns the elapsed time since solicit starts.
588      *
589      * @returns The elapsed time since solicit starts.
590      *
591      */
GetElapsedTime(void) const592     uint16_t GetElapsedTime(void) const { return BigEndian::HostSwap16(mElapsedTime); }
593 
594     /**
595      * Sets the elapsed time since solicit starts.
596      *
597      * @param[in] aElapsedTime The elapsed time since solicit starts.
598      *
599      */
SetElapsedTime(uint16_t aElapsedTime)600     void SetElapsedTime(uint16_t aElapsedTime) { mElapsedTime = BigEndian::HostSwap16(aElapsedTime); }
601 
602 private:
603     uint16_t mElapsedTime;
604 } OT_TOOL_PACKED_END;
605 
606 /**
607  * Status Code.
608  *
609  */
610 enum Status : uint16_t
611 {
612     kStatusSuccess      = 0,
613     kStatusUnspecFail   = 1,
614     kStatusNoAddrsAvail = 2,
615     kStatusNoBinding    = 3,
616     kStatusNotOnLink    = 4,
617     kStatusUseMulticast = 5,
618     kUnknownQueryType   = 7,
619     kMalformedQuery     = 8,
620     kNotConfigured      = 9,
621     kNotAllowed         = 10,
622 };
623 
624 /**
625  * Represents an Status Code DHCPv6 option.
626  *
627  */
628 OT_TOOL_PACKED_BEGIN
629 class StatusCode : public Option
630 {
631 public:
632     /**
633      * Initializes the DHCPv6 Option.
634      *
635      */
Init(void)636     void Init(void)
637     {
638         SetCode(kOptionStatusCode);
639         SetLength(sizeof(*this) - sizeof(Option));
640     }
641 
642     /**
643      * Returns the status code.
644      *
645      * @returns The status code.
646      *
647      */
GetStatusCode(void) const648     Status GetStatusCode(void) const { return static_cast<Status>(BigEndian::HostSwap16(mStatus)); }
649 
650     /**
651      * Sets the status code.
652      *
653      * @param[in] aStatus The status code.
654      *
655      */
SetStatusCode(Status aStatus)656     void SetStatusCode(Status aStatus) { mStatus = BigEndian::HostSwap16(static_cast<uint16_t>(aStatus)); }
657 
658 private:
659     uint16_t mStatus;
660 } OT_TOOL_PACKED_END;
661 
662 /**
663  * Represents an Rapid Commit DHCPv6 option.
664  *
665  */
666 OT_TOOL_PACKED_BEGIN
667 class RapidCommit : public Option
668 {
669 public:
670     /**
671      * Initializes the DHCPv6 Option.
672      *
673      */
Init(void)674     void Init(void)
675     {
676         SetCode(kOptionRapidCommit);
677         SetLength(sizeof(*this) - sizeof(Option));
678     }
679 } OT_TOOL_PACKED_END;
680 
681 } // namespace Dhcp6
682 } // namespace ot
683 
684 #endif // #if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE || OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
685 
686 #endif // DHCP6_HPP_
687