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