• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 implements IP4 headers processing.
32  */
33 
34 #include "ip4_types.hpp"
35 #include "ip6_address.hpp"
36 
37 namespace ot {
38 namespace Ip4 {
39 
FromString(const char * aString)40 Error Address::FromString(const char *aString)
41 {
42     constexpr char kSeperatorChar = '.';
43     constexpr char kNullChar      = '\0';
44 
45     Error error = kErrorParse;
46 
47     for (uint8_t index = 0;; index++)
48     {
49         uint16_t value         = 0;
50         uint8_t  hasFirstDigit = false;
51 
52         for (char digitChar = *aString;; ++aString, digitChar = *aString)
53         {
54             if ((digitChar < '0') || (digitChar > '9'))
55             {
56                 break;
57             }
58 
59             value = static_cast<uint16_t>((value * 10) + static_cast<uint8_t>(digitChar - '0'));
60             VerifyOrExit(value <= NumericLimits<uint8_t>::kMax);
61             hasFirstDigit = true;
62         }
63 
64         VerifyOrExit(hasFirstDigit);
65 
66         mFields.m8[index] = static_cast<uint8_t>(value);
67 
68         if (index == sizeof(Address) - 1)
69         {
70             break;
71         }
72 
73         VerifyOrExit(*aString == kSeperatorChar);
74         aString++;
75     }
76 
77     VerifyOrExit(*aString == kNullChar);
78     error = kErrorNone;
79 
80 exit:
81     return error;
82 }
83 
ExtractFromIp6Address(uint8_t aPrefixLength,const Ip6::Address & aIp6Address)84 void Address::ExtractFromIp6Address(uint8_t aPrefixLength, const Ip6::Address &aIp6Address)
85 {
86     // The prefix length must be 32, 40, 48, 56, 64, 96. IPv4 bytes are added
87     // after the prefix, skipping over the bits 64 to 71 (byte at `kSkipIndex`)
88     // which must be set to zero. The suffix is set to zero (per RFC 6502).
89     //
90     //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
91     //    |PL| 0-------------32--40--48--56--64--72--80--88--96--104---------|
92     //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
93     //    |32|     prefix    |v4(32)         | u | suffix                    |
94     //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
95     //    |40|     prefix        |v4(24)     | u |(8)| suffix                |
96     //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
97     //    |48|     prefix            |v4(16) | u | (16)  | suffix            |
98     //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
99     //    |56|     prefix                |(8)| u |  v4(24)   | suffix        |
100     //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
101     //    |64|     prefix                    | u |   v4(32)      | suffix    |
102     //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
103     //    |96|     prefix                                    |    v4(32)     |
104     //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
105 
106     constexpr uint8_t kSkipIndex = 8;
107 
108     uint8_t ip6Index;
109 
110     OT_ASSERT(Ip6::Prefix::IsValidNat64PrefixLength(aPrefixLength));
111 
112     ip6Index = aPrefixLength / CHAR_BIT;
113 
114     for (uint8_t i = 0; i < Ip4::Address::kSize; i++)
115     {
116         if (ip6Index == kSkipIndex)
117         {
118             ip6Index++;
119         }
120 
121         mFields.m8[i] = aIp6Address.GetBytes()[ip6Index++];
122     }
123 }
124 
SynthesizeFromCidrAndHost(const Cidr & aCidr,const uint32_t aHost)125 void Address::SynthesizeFromCidrAndHost(const Cidr &aCidr, const uint32_t aHost)
126 {
127     mFields.m32 = (aCidr.mAddress.mFields.m32 & aCidr.SubnetMask()) | (HostSwap32(aHost) & aCidr.HostMask());
128 }
129 
ToString(void) const130 Address::InfoString Address::ToString(void) const
131 {
132     InfoString string;
133 
134     string.Append("%d.%d.%d.%d", mFields.m8[0], mFields.m8[1], mFields.m8[2], mFields.m8[3]);
135 
136     return string;
137 }
138 
ToString(void) const139 Cidr::InfoString Cidr::ToString(void) const
140 {
141     InfoString string;
142 
143     string.Append("%s/%d", AsCoreType(&mAddress).ToString().AsCString(), mLength);
144 
145     return string;
146 }
147 
operator ==(const Cidr & aOther) const148 bool Cidr::operator==(const Cidr &aOther) const
149 {
150     return (mLength == aOther.mLength) &&
151            (Ip6::Prefix::MatchLength(GetBytes(), aOther.GetBytes(), Ip4::Address::kSize) >= mLength);
152 }
153 
Set(const uint8_t * aAddress,uint8_t aLength)154 void Cidr::Set(const uint8_t *aAddress, uint8_t aLength)
155 {
156     memcpy(mAddress.mFields.m8, aAddress, Ip4::Address::kSize);
157     mLength = aLength;
158 }
159 
ParseFrom(const Message & aMessage)160 Error Header::ParseFrom(const Message &aMessage)
161 {
162     Error error = kErrorParse;
163 
164     SuccessOrExit(aMessage.Read(0, *this));
165     VerifyOrExit(IsValid());
166     VerifyOrExit(GetTotalLength() == aMessage.GetLength());
167 
168     error = kErrorNone;
169 
170 exit:
171     return error;
172 }
173 
174 } // namespace Ip4
175 } // namespace ot
176