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