1 /*
2  *  Copyright (c) 2022, 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 IPv4 packet processing.
32  */
33 
34 #ifndef IP4_TYPES_HPP_
35 #define IP4_TYPES_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <stddef.h>
40 
41 #include <openthread/nat64.h>
42 
43 #include "common/clearable.hpp"
44 #include "common/encoding.hpp"
45 #include "common/message.hpp"
46 #include "net/ip6_types.hpp"
47 #include "net/netif.hpp"
48 #include "net/socket.hpp"
49 #include "net/tcp6.hpp"
50 #include "net/udp6.hpp"
51 
52 namespace ot {
53 
54 namespace Ip6 {
55 // Forward declaration for ExtractFromIp4Address
56 class Address;
57 } // namespace Ip6
58 
59 /**
60  * @namespace ot::Ip4
61  *
62  * @brief
63  *   This namespace includes definitions for IPv4 networking used by NAT64.
64  *
65  */
66 namespace Ip4 {
67 
68 using Encoding::BigEndian::HostSwap16;
69 using Encoding::BigEndian::HostSwap32;
70 
71 using Ecn = Ip6::Ecn;
72 
73 /**
74  * @addtogroup core-ipv4
75  *
76  * @brief
77  *   This module includes definitions for the IPv4 network layer.
78  *
79  */
80 
81 /**
82  * @addtogroup core-ip4-ip4
83  *
84  * @brief
85  *   This module includes definitions for IPv4 networking used by NAT64.
86  *
87  * @{
88  *
89  */
90 
91 // Forward declaration for Address::SynthesizeFromCidrAndHost
92 class Cidr;
93 
94 /**
95  * This class represents an IPv4 address.
96  *
97  */
98 OT_TOOL_PACKED_BEGIN
99 class Address : public otIp4Address, public Equatable<Address>, public Clearable<Address>
100 {
101 public:
102     static constexpr uint16_t kSize              = 4;  ///< Size of an IPv4 Address (in bytes).
103     static constexpr uint16_t kAddressStringSize = 17; ///< String size used by `ToString()`.
104 
105     /**
106      * This type defines the fixed-length `String` object returned from `ToString()`.
107      *
108      */
109     typedef String<kAddressStringSize> InfoString;
110 
111     /**
112      * This method gets the IPv4 address as a pointer to a byte array.
113      *
114      * @returns A pointer to a byte array containing the IPv4 address.
115      *
116      */
GetBytes(void) const117     const uint8_t *GetBytes(void) const { return mFields.m8; }
118 
119     /**
120      * This method sets the IPv4 address from a given byte array.
121      *
122      * @param[in] aBuffer    Pointer to an array containing the IPv4 address. `kSize` bytes from the buffer
123      *                       are copied to form the IPv4 address.
124      *
125      */
SetBytes(const uint8_t * aBuffer)126     void SetBytes(const uint8_t *aBuffer) { memcpy(mFields.m8, aBuffer, kSize); }
127 
128     /**
129      * This method sets the IPv4 address by performing NAT64 address translation from a given IPv6 address as specified
130      * in RFC 6052.
131      *
132      * The NAT64 @p aPrefixLength MUST be one of the following values: 32, 40, 48, 56, 64, or 96, otherwise the behavior
133      * of this method is undefined.
134      *
135      * @param[in] aPrefixLength      The prefix length to use for IPv4/IPv6 translation.
136      * @param[in] aIp6Address  The IPv6 address to translate to IPv4.
137      *
138      */
139     void ExtractFromIp6Address(uint8_t aPrefixLength, const Ip6::Address &aIp6Address);
140 
141     /**
142      * This method sets the IPv4 address from the given CIDR and the host field.
143      *
144      * @param[in] aCidr The CIDR for the IPv4 address.
145      * @param[in] aHost The host bits of the IPv4 address in host byte order. The aHost will be masked by host mask.
146      *
147      */
148     void SynthesizeFromCidrAndHost(const Cidr &aCidr, uint32_t aHost);
149 
150     /**
151      * This method parses an IPv4 address string terminated by `aTerminatorChar`.
152      *
153      * The string MUST follow the quad-dotted notation of four decimal values (ranging from 0 to 255 each). For
154      * example, "127.0.0.1"
155      *
156      * @param[in]  aString        A pointer to the null-terminated string.
157      *
158      * @retval kErrorNone         Successfully parsed the IPv4 address string.
159      * @retval kErrorParse        Failed to parse the IPv4 address string.
160      *
161      */
162     Error FromString(const char *aString, char aTerminatorChar = kNullChar);
163 
164     /**
165      * This method converts the address to a string.
166      *
167      * The string format uses quad-dotted notation of four bytes in the address (e.g., "127.0.0.1").
168      *
169      * If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be
170      * truncated but the outputted string is always null-terminated.
171      *
172      * @param[out] aBuffer   A pointer to a char array to output the string (MUST NOT be `nullptr`).
173      * @param[in]  aSize     The size of @p aBuffer (in bytes).
174      *
175      */
176     void ToString(char *aBuffer, uint16_t aSize) const;
177 
178     /**
179      * This method converts the IPv4 address to a string.
180      *
181      * The string format uses quad-dotted notation of four bytes in the address (e.g., "127.0.0.1").
182      *
183      * @returns An `InfoString` representing the IPv4 address.
184      *
185      */
186     InfoString ToString(void) const;
187 
188 private:
189     void ToString(StringWriter &aWriter) const;
190 } OT_TOOL_PACKED_END;
191 
192 /**
193  * This class represents an IPv4 CIDR block.
194  *
195  */
196 class Cidr : public otIp4Cidr, public Unequatable<Cidr>, public Clearable<Address>
197 {
198     friend class Address;
199 
200 public:
201     static constexpr uint16_t kCidrSuffixSize = 3; ///< Suffix to represent CIDR (/dd).
202 
203     /**
204      * This type defines the fixed-length `String` object returned from `ToString()`.
205      *
206      */
207     typedef String<Address::kAddressStringSize + kCidrSuffixSize> InfoString;
208 
209     /**
210      * This method converts the IPv4 CIDR string to binary.
211      *
212      * The string format uses quad-dotted notation of four bytes in the address with the length of prefix (e.g.,
213      * "127.0.0.1/32").
214      *
215      * @param[in]  aString  A pointer to the null-terminated string.
216      *
217      * @retval kErrorNone          Successfully parsed the IPv4 CIDR string.
218      * @retval kErrorParse         Failed to parse the IPv4 CIDR string.
219      *
220      */
221     Error FromString(const char *aString);
222 
223     /**
224      * This method converts the IPv4 CIDR to a string.
225      *
226      * The string format uses quad-dotted notation of four bytes in the address with the length of prefix (e.g.,
227      * "127.0.0.1/32").
228      *
229      * If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be
230      * truncated but the outputted string is always null-terminated.
231      *
232      * @param[out] aBuffer   A pointer to a char array to output the string (MUST NOT be `nullptr`).
233      * @param[in]  aSize     The size of @p aBuffer (in bytes).
234      *
235      */
236     void ToString(char *aBuffer, uint16_t aSize) const;
237 
238     /**
239      * This method converts the IPv4 CIDR to a string.
240      *
241      * The string format uses quad-dotted notation of four bytes in the address with the length of prefix (e.g.,
242      * "127.0.0.1/32").
243      *
244      * @returns An `InfoString` representing the IPv4 cidr.
245      *
246      */
247     InfoString ToString(void) const;
248 
249     /**
250      * This method gets the prefix as a pointer to a byte array.
251      *
252      * @returns A pointer to a byte array containing the Prefix.
253      *
254      */
GetBytes(void) const255     const uint8_t *GetBytes(void) const { return mAddress.mFields.m8; }
256 
257     /**
258      * This method overloads operator `==` to evaluate whether or not two prefixes are equal.
259      *
260      * @param[in]  aOther  The other prefix to compare with.
261      *
262      * @retval TRUE   If the two prefixes are equal.
263      * @retval FALSE  If the two prefixes are not equal.
264      *
265      */
266     bool operator==(const Cidr &aOther) const;
267 
268     /**
269      * This method sets the CIDR.
270      *
271      * @param[in] aAddress  A pointer to buffer containing the CIDR bytes. The length of aAddress should be 4 bytes.
272      * @param[in] aLength   The length of CIDR in bits.
273      *
274      */
275     void Set(const uint8_t *aAddress, uint8_t aLength);
276 
277 private:
HostMask(void) const278     uint32_t HostMask(void) const
279     {
280         // Note: Using LL suffix to make it a uint64 since /32 is a valid CIDR, and right shifting 32 bits is undefined
281         // for uint32.
282         return HostSwap32(0xffffffffLL >> mLength);
283     }
284 
SubnetMask(void) const285     uint32_t SubnetMask(void) const { return ~HostMask(); }
286 
287     void ToString(StringWriter &aWriter) const;
288 };
289 
290 /**
291  * This class implements IPv4 header generation and parsing.
292  *
293  */
294 OT_TOOL_PACKED_BEGIN
295 class Header : public Clearable<Header>
296 {
297 public:
298     static constexpr uint8_t kVersionIhlOffset         = 0;
299     static constexpr uint8_t kTrafficClassOffset       = 1;
300     static constexpr uint8_t kTotalLengthOffset        = 2;
301     static constexpr uint8_t kIdentificationOffset     = 4;
302     static constexpr uint8_t kFlagsFragmentOffset      = 6;
303     static constexpr uint8_t kTtlOffset                = 8;
304     static constexpr uint8_t kProtocolOffset           = 9;
305     static constexpr uint8_t kHeaderChecksumOffset     = 10;
306     static constexpr uint8_t kSourceAddressOffset      = 12;
307     static constexpr uint8_t kDestinationAddressOffset = 16;
308 
309     /**
310      * This method indicates whether or not the header appears to be well-formed.
311      *
312      * @retval TRUE    If the header appears to be well-formed.
313      * @retval FALSE   If the header does not appear to be well-formed.
314      *
315      */
IsValid(void) const316     bool IsValid(void) const { return IsVersion4(); }
317 
318     /**
319      * This method initializes the Version to 4 and sets Traffic Class and Flow fields to zero.
320      *
321      * The other fields in the IPv4 header remain unchanged.
322      *
323      */
InitVersionIhl(void)324     void InitVersionIhl(void) { SetVersionIhl(kVersIhlInit); }
325 
326     /**
327      * This method sets the version and Ihl of the IPv4 header.
328      *
329      * @param[in] aVersionIhl The octet for the version and Ihl field.
330      *
331      */
SetVersionIhl(uint8_t aVersionIhl)332     void SetVersionIhl(uint8_t aVersionIhl) { mVersIhl = aVersionIhl; }
333 
334     /**
335      * This method indicates whether or not the IPv4 Version is set to 6.
336      *
337      * @retval TRUE   If the IPv4 Version is set to 4.
338      * @retval FALSE  If the IPv4 Version is not set to 4.
339      *
340      */
IsVersion4(void) const341     bool IsVersion4(void) const { return (mVersIhl & kVersionMask) == kVersion4; }
342 
343     /**
344      * This method returns the octet for DSCP + ECN.
345      *
346      * @retval The octet for DSCP and ECN.
347      *
348      */
GetDscpEcn(void) const349     uint8_t GetDscpEcn(void) const { return mDscpEcn; }
350 
351     /**
352      * This method gets the 6-bit Differentiated Services Code Point (DSCP) from Traffic Class field.
353      *
354      * @returns The DSCP value.
355      *
356      */
GetDscp(void) const357     uint8_t GetDscp(void) const { return (mDscpEcn & kDscpMask) >> kDscpOffset; }
358 
359     /**
360      * This method sets 6-bit Differentiated Services Code Point (DSCP) in IPv4 header.
361      *
362      * @param[in]  aDscp  The DSCP value.
363      *
364      */
SetDscp(uint8_t aDscp)365     void SetDscp(uint8_t aDscp) { mDscpEcn = static_cast<uint8_t>((mDscpEcn & ~kDscpMask) | (aDscp << kDscpOffset)); }
366 
367     /**
368      * This method gets the 2-bit Explicit Congestion Notification (ECN) from Traffic Class field.
369      *
370      * @returns The ECN value.
371      *
372      */
GetEcn(void) const373     Ecn GetEcn(void) const { return static_cast<Ecn>(mDscpEcn & kEcnMask); }
374 
375     /**
376      * This method sets the 2-bit Explicit Congestion Notification (ECN) in IPv4 header..
377      *
378      * @param[in]  aEcn  The ECN value.
379      *
380      */
SetEcn(Ecn aEcn)381     void SetEcn(Ecn aEcn) { mDscpEcn = ((mDscpEcn & ~kEcnMask) | aEcn); }
382 
383     /**
384      * This method returns the IPv4 Payload Length value.
385      *
386      * @returns The IPv4 Payload Length value.
387      *
388      */
GetTotalLength(void) const389     uint16_t GetTotalLength(void) const { return HostSwap16(mTotalLength); }
390 
391     /**
392      * This method sets the IPv4 Payload Length value.
393      *
394      * @param[in]  aLength  The IPv4 Payload Length value.
395      *
396      */
SetTotalLength(uint16_t aLength)397     void SetTotalLength(uint16_t aLength) { mTotalLength = HostSwap16(aLength); }
398 
399     /**
400      * This method returns the IPv4 payload protocol.
401      *
402      * @returns The IPv4 payload protocol value.
403      *
404      */
GetProtocol(void) const405     uint8_t GetProtocol(void) const { return mProtocol; }
406 
407     /**
408      * This method sets the IPv4 payload protocol.
409      *
410      * @param[in]  aProtocol  The IPv4 payload protocol.
411      *
412      */
SetProtocol(uint8_t aProtocol)413     void SetProtocol(uint8_t aProtocol) { mProtocol = aProtocol; }
414 
415     /**
416      * This method returns the IPv4 header checksum, the checksum is in host endian.
417      *
418      * @returns The checksum field in the IPv4 header.
419      *
420      */
GetChecksum(void) const421     uint16_t GetChecksum(void) const { return HostSwap16(mHeaderChecksum); }
422 
423     /**
424      * This method sets the IPv4 header checksum, the checksum is in host endian.
425      *
426      * @param[in] aChecksum The checksum for the IPv4 header.
427      *
428      */
SetChecksum(uint16_t aChecksum)429     void SetChecksum(uint16_t aChecksum) { mHeaderChecksum = HostSwap16(aChecksum); }
430 
431     /**
432      * This method returns the IPv4 Identification value.
433      *
434      * @returns The IPv4 Identification value.
435      *
436      */
GetIdentification(void) const437     uint16_t GetIdentification(void) const { return HostSwap16(mIdentification); }
438 
439     /**
440      * This method sets the IPv4 Identification value.
441      *
442      * @param[in] aIdentification The IPv4 Identification value.
443      *
444      */
SetIdentification(uint16_t aIdentification)445     void SetIdentification(uint16_t aIdentification) { mIdentification = HostSwap16(aIdentification); }
446 
447     /**
448      * This method returns the IPv4 Time-to-Live value.
449      *
450      * @returns The IPv4 Time-to-Live value.
451      *
452      */
GetTtl(void) const453     uint8_t GetTtl(void) const { return mTtl; }
454 
455     /**
456      * This method sets the IPv4 Time-to-Live value.
457      *
458      * @param[in]  aTtl  The IPv4 Time-to-Live value.
459      *
460      */
SetTtl(uint8_t aTtl)461     void SetTtl(uint8_t aTtl) { mTtl = aTtl; }
462 
463     /**
464      * This method returns the IPv4 Source address.
465      *
466      * @returns A reference to the IPv4 Source address.
467      *
468      */
GetSource(void)469     Address &GetSource(void) { return mSource; }
470 
471     /**
472      * This method returns the IPv4 Source address.
473      *
474      * @returns A reference to the IPv4 Source address.
475      *
476      */
GetSource(void) const477     const Address &GetSource(void) const { return mSource; }
478 
479     /**
480      * This method sets the IPv4 Source address.
481      *
482      * @param[in]  aSource  A reference to the IPv4 Source address.
483      *
484      */
SetSource(const Address & aSource)485     void SetSource(const Address &aSource) { mSource = aSource; }
486 
487     /**
488      * This method returns the IPv4 Destination address.
489      *
490      * @returns A reference to the IPv4 Destination address.
491      *
492      */
GetDestination(void)493     Address &GetDestination(void) { return mDestination; }
494 
495     /**
496      * This method returns the IPv4 Destination address.
497      *
498      * @returns A reference to the IPv4 Destination address.
499      *
500      */
GetDestination(void) const501     const Address &GetDestination(void) const { return mDestination; }
502 
503     /**
504      * This method sets the IPv4 Destination address.
505      *
506      * @param[in]  aDestination  A reference to the IPv4 Destination address.
507      *
508      */
SetDestination(const Address & aDestination)509     void SetDestination(const Address &aDestination) { mDestination = aDestination; }
510 
511     /**
512      * This method parses and validates the IPv4 header from a given message.
513      *
514      * The header is read from @p aMessage at offset zero.
515      *
516      * @param[in]  aMessage  The IPv4 message.
517      *
518      * @retval kErrorNone   Successfully parsed the IPv4 header from @p aMessage.
519      * @retval kErrorParse  Malformed IPv4 header or message (e.g., message does not contained expected payload length).
520      *
521      */
522     Error ParseFrom(const Message &aMessage);
523 
524     /**
525      * This method returns the Df flag in the IPv4 header.
526      *
527      * @returns Whether don't fragment flag is set.
528      *
529      */
GetDf(void) const530     bool GetDf(void) const { return HostSwap16(mFlagsFragmentOffset) & kFlagsDf; }
531 
532     /**
533      * This method returns the Mf flag in the IPv4 header.
534      *
535      * @returns Whether more fragments flag is set.
536      *
537      */
GetMf(void) const538     bool GetMf(void) const { return HostSwap16(mFlagsFragmentOffset) & kFlagsMf; }
539 
540     /**
541      * This method returns the fragment offset in the IPv4 header.
542      *
543      * @returns The fragment offset of the IPv4 packet.
544      *
545      */
GetFragmentOffset(void) const546     uint16_t GetFragmentOffset(void) const { return HostSwap16(mFlagsFragmentOffset) & kFragmentOffsetMask; }
547 
548 private:
549     // IPv4 header
550     //
551     // +---------------+---------------+---------------+---------------+
552     // |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|
553     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
554     // |Version|  IHL  |    DSCP   |ECN|         Total Length          |
555     // |        Identification         |Flags|    Fragment Offset      |
556     // |      TTL      |    Protocol   |        Header Checksum        |
557     // |                       Source IP Address                       |
558     // |                         Dest IP Address                       |
559     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
560 
561     static constexpr uint8_t  kVersion4           = 0x40;   // Use with `mVersIhl`
562     static constexpr uint8_t  kVersionMask        = 0xf0;   // Use with `mVersIhl`
563     static constexpr uint8_t  kIhlMask            = 0x0f;   // Use with `mVersIhl`
564     static constexpr uint8_t  kDscpOffset         = 2;      // Use with `mDscpEcn`
565     static constexpr uint16_t kDscpMask           = 0xfc;   // Use with `mDscpEcn`
566     static constexpr uint8_t  kEcnOffset          = 0;      // Use with `mDscpEcn`
567     static constexpr uint8_t  kEcnMask            = 0x03;   // Use with `mDscpEcn`
568     static constexpr uint16_t kFlagsMask          = 0xe000; // Use with `mFlagsFragmentOffset`
569     static constexpr uint16_t kFlagsDf            = 0x4000; // Use with `mFlagsFragmentOffset`
570     static constexpr uint16_t kFlagsMf            = 0x2000; // Use with `mFlagsFragmentOffset`
571     static constexpr uint16_t kFragmentOffsetMask = 0x1fff; // Use with `mFlagsFragmentOffset`
572     static constexpr uint32_t kVersIhlInit        = 0x45;   // Version 4, Header length = 5x8 bytes.
573 
574     uint8_t  mVersIhl;
575     uint8_t  mDscpEcn;
576     uint16_t mTotalLength;
577     uint16_t mIdentification;
578     uint16_t mFlagsFragmentOffset;
579     uint8_t  mTtl;
580     uint8_t  mProtocol;
581     uint16_t mHeaderChecksum;
582     Address  mSource;
583     Address  mDestination;
584 } OT_TOOL_PACKED_END;
585 
586 /**
587  * This class implements ICMP(v4).
588  * Note: ICMP(v4) messages will only be generated / handled by NAT64. So only header definition is required.
589  *
590  */
591 class Icmp
592 {
593 public:
594     /**
595      * This class represents an IPv4 ICMP header.
596      *
597      */
598     OT_TOOL_PACKED_BEGIN
599     class Header : public Clearable<Header>
600     {
601     public:
602         static constexpr uint16_t kChecksumFieldOffset = 2;
603         // A few ICMP types, only the ICMP types work with NAT64 are listed here.
604         enum Type : uint8_t
605         {
606             kTypeEchoReply              = 0,
607             kTypeDestinationUnreachable = 3,
608             kTypeEchoRequest            = 8,
609             kTypeTimeExceeded           = 11,
610         };
611 
612         enum Code : uint8_t
613         {
614             kCodeNone = 0,
615             // Destination Unreachable codes
616             kCodeNetworkUnreachable  = 0,
617             kCodeHostUnreachable     = 1,
618             kCodeProtocolUnreachable = 2,
619             kCodePortUnreachable     = 3,
620             kCodeSourceRouteFailed   = 5,
621             kCodeNetworkUnknown      = 6,
622             kCodeHostUnknown         = 7,
623         };
624 
625         /**
626          * This method returns the type of the ICMP message.
627          *
628          * @returns The type field of the ICMP message.
629          *
630          */
GetType(void) const631         uint8_t GetType(void) const { return mType; }
632 
633         /**
634          * This method sets the type of the ICMP message.
635          *
636          * @param[in] aType The type of the ICMP message.
637          *
638          */
SetType(uint8_t aType)639         void SetType(uint8_t aType) { mType = aType; }
640 
641         /**
642          * This method returns the code of the ICMP message.
643          *
644          * @returns The code field of the ICMP message.
645          *
646          */
GetCode(void) const647         uint8_t GetCode(void) const { return mCode; }
648 
649         /**
650          * This method sets the code of the ICMP message.
651          *
652          * @param[in] aCode The code of the ICMP message.
653          *
654          */
SetCode(uint8_t aCode)655         void SetCode(uint8_t aCode) { mCode = aCode; }
656 
657         /**
658          * This method sets the checksum field in the ICMP message.
659          *
660          * @returns The checksum of the ICMP message.
661          *
662          */
GetChecksum(void) const663         uint16_t GetChecksum(void) const { return HostSwap16(mChecksum); }
664 
665         /**
666          * This method sets the checksum field in the ICMP message.
667          *
668          * @param[in] aChecksum The checksum of the ICMP message.
669          *
670          */
SetChecksum(uint16_t aChecksum)671         void SetChecksum(uint16_t aChecksum) { mChecksum = HostSwap16(aChecksum); }
672 
673         /**
674          * This method returns the rest of header field in the ICMP message.
675          *
676          * @returns The rest of header field in the ICMP message. The returned buffer has 4 octets.
677          *
678          */
GetRestOfHeader(void) const679         const uint8_t *GetRestOfHeader(void) const { return mRestOfHeader; }
680 
681         /**
682          * This method sets the rest of header field in the ICMP message.
683          *
684          * @param[in] aRestOfHeader The rest of header field in the ICMP message. The buffer should have 4 octets.
685          *
686          */
SetRestOfHeader(const uint8_t * aRestOfHeader)687         void SetRestOfHeader(const uint8_t *aRestOfHeader)
688         {
689             memcpy(mRestOfHeader, aRestOfHeader, sizeof(mRestOfHeader));
690         }
691 
692     private:
693         uint8_t  mType;
694         uint8_t  mCode;
695         uint16_t mChecksum;
696         uint8_t  mRestOfHeader[4];
697     } OT_TOOL_PACKED_END;
698 };
699 
700 // Internet Protocol Numbers
701 static constexpr uint8_t kProtoTcp  = Ip6::kProtoTcp; ///< Transmission Control Protocol
702 static constexpr uint8_t kProtoUdp  = Ip6::kProtoUdp; ///< User Datagram
703 static constexpr uint8_t kProtoIcmp = 1;              ///< ICMP for IPv4
704 
705 using Tcp = Ip6::Tcp; // TCP in IPv4 is the same as TCP in IPv6
706 using Udp = Ip6::Udp; // UDP in IPv4 is the same as UDP in IPv6
707 
708 /**
709  * @}
710  *
711  */
712 
713 } // namespace Ip4
714 
715 DefineCoreType(otIp4Address, Ip4::Address);
716 DefineCoreType(otIp4Cidr, Ip4::Cidr);
717 
718 } // namespace ot
719 
720 #endif // IP4_TYPES_HPP_
721