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