blob: 3546df5acb06575bc3c4ce9df26a6d6fd49f88a0 [file] [log] [blame]
Pankaj Garg2efbcce2020-03-10 12:05:08 -07001/*
2 *
Rob Walkere812e672020-03-31 17:51:57 -07003 * Copyright (c) 2020 Project CHIP Authors
4 * Copyright (c) 2019 Google LLC.
5 * Copyright (c) 2013-2018 Nest Labs, Inc.
Pankaj Garg2efbcce2020-03-10 12:05:08 -07006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20/**
21 * @file
22 * This file implements the class <tt>Inet::IPAddress</tt> and
Sagar Dhawand1b63752020-03-17 14:35:27 -070023 * related enumerated constants. The CHIP Inet Layer uses objects
Pankaj Garg2efbcce2020-03-10 12:05:08 -070024 * of this class to represent Internet protocol addresses of both
25 * IPv4 and IPv6 address families. (IPv4 addresses are stored
Kevin Schoedel33ca5222021-10-22 10:50:21 -040026 * internally as IPv4-Mapped IPv6 addresses.)
Pankaj Garg2efbcce2020-03-10 12:05:08 -070027 *
28 */
29
30#ifndef __STDC_LIMIT_MACROS
31#define __STDC_LIMIT_MACROS
32#endif
Rob Walker29e104a2020-05-13 20:38:36 -070033
Michael Spang719d1162020-06-25 12:58:42 -040034#include <inet/IPAddress.h>
Pankaj Garg2efbcce2020-03-10 12:05:08 -070035
Kevin Schoedel4b9ead62022-01-04 11:09:42 -050036#include <inet/InetError.h>
Zang MingJie53dd5832021-09-03 03:05:16 +080037#include <lib/core/CHIPEncoding.h>
Kevin Schoedel4b9ead62022-01-04 11:09:42 -050038#include <lib/support/CodeUtils.h>
Pankaj Garg2efbcce2020-03-10 12:05:08 -070039
40#include "arpa-inet-compatibility.h"
41
Rob Walker29e104a2020-05-13 20:38:36 -070042#include <stdint.h>
43#include <string.h>
44
Pankaj Garg2efbcce2020-03-10 12:05:08 -070045namespace chip {
46namespace Inet {
47
48IPAddress IPAddress::Any;
49
Rob Walker6f431212020-03-13 11:56:19 -070050bool IPAddress::operator==(const IPAddress & other) const
Pankaj Garg2efbcce2020-03-10 12:05:08 -070051{
52 return Addr[0] == other.Addr[0] && Addr[1] == other.Addr[1] && Addr[2] == other.Addr[2] && Addr[3] == other.Addr[3];
53}
54
Rob Walker6f431212020-03-13 11:56:19 -070055bool IPAddress::operator!=(const IPAddress & other) const
Pankaj Garg2efbcce2020-03-10 12:05:08 -070056{
57 return Addr[0] != other.Addr[0] || Addr[1] != other.Addr[1] || Addr[2] != other.Addr[2] || Addr[3] != other.Addr[3];
58}
59
Jean-Francois Penven75bdf792022-04-14 13:32:17 -040060#if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT
Pankaj Garg2efbcce2020-03-10 12:05:08 -070061
Kevin Schoedel33ca5222021-10-22 10:50:21 -040062IPAddress::IPAddress(const ip6_addr_t & ipv6Addr)
63{
Praveen Chandrand5810e52021-11-02 20:04:00 -070064 static_assert(sizeof(ipv6Addr.addr) == sizeof(Addr), "ip6_addr_t size mismatch");
65 memcpy(Addr, &ipv6Addr.addr, sizeof(ipv6Addr.addr));
Kevin Schoedel33ca5222021-10-22 10:50:21 -040066}
67
Kevin Schoedel8a166dd2021-10-22 20:24:58 -040068#if INET_CONFIG_ENABLE_IPV4 || LWIP_IPV4
Kevin Schoedel33ca5222021-10-22 10:50:21 -040069
70IPAddress::IPAddress(const ip4_addr_t & ipv4Addr)
71{
72 Addr[0] = 0;
73 Addr[1] = 0;
74 Addr[2] = htonl(0xFFFF);
75 Addr[3] = ipv4Addr.addr;
76}
77
78IPAddress::IPAddress(const ip_addr_t & addr)
79{
80 switch (IP_GET_TYPE(&addr))
81 {
82#if INET_CONFIG_ENABLE_IPV4
83 case IPADDR_TYPE_V4:
84 *this = IPAddress(*ip_2_ip4(&addr));
85 break;
86#endif // INET_CONFIG_ENABLE_IPV4
87
88 case IPADDR_TYPE_V6:
89 *this = IPAddress(*ip_2_ip6(&addr));
90 break;
91
92 default:
93 *this = Any;
94 break;
95 }
96}
97
Kevin Schoedel8a166dd2021-10-22 20:24:58 -040098#endif // INET_CONFIG_ENABLE_IPV4 || LWIP_IPV4
99
100#if INET_CONFIG_ENABLE_IPV4
101
Kevin Schoedel33ca5222021-10-22 10:50:21 -0400102ip4_addr_t IPAddress::ToIPv4() const
103{
104 ip4_addr_t ipAddr;
105 memcpy(&ipAddr, &Addr[3], sizeof(ipAddr));
106 return ipAddr;
107}
108
109#endif // INET_CONFIG_ENABLE_IPV4
110
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700111ip_addr_t IPAddress::ToLwIPAddr(void) const
112{
113 ip_addr_t ret;
114
115 switch (Type())
116 {
117#if INET_CONFIG_ENABLE_IPV4
Kevin Schoedel77b06032021-10-21 09:15:11 -0400118 case IPAddressType::kIPv4:
Kevin Schoedel4b9ead62022-01-04 11:09:42 -0500119 ip_addr_copy_from_ip4(ret, IPAddress::ToIPv4());
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700120 break;
121#endif // INET_CONFIG_ENABLE_IPV4
122
Kevin Schoedel77b06032021-10-21 09:15:11 -0400123 case IPAddressType::kIPv6:
Kevin Schoedel4b9ead62022-01-04 11:09:42 -0500124 ip_addr_copy_from_ip6(ret, IPAddress::ToIPv6());
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700125 break;
126
127 default:
Andrei Litvin5987dab2021-10-18 12:02:49 -0400128 ret = *IP6_ADDR_ANY;
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700129 break;
130 }
131
132 return ret;
133}
134
Kevin Schoedel4b9ead62022-01-04 11:09:42 -0500135CHIP_ERROR IPAddress::ToLwIPAddr(IPAddressType addressType, ip_addr_t & outAddress) const
136{
137 VerifyOrReturnError(addressType != IPAddressType::kUnknown, CHIP_ERROR_INVALID_ARGUMENT);
138
139 switch (Type())
140 {
141#if INET_CONFIG_ENABLE_IPV4
142 case IPAddressType::kIPv4:
143 ip_addr_copy_from_ip4(outAddress, IPAddress::ToIPv4());
144 return (addressType == IPAddressType::kIPv6) ? INET_ERROR_WRONG_ADDRESS_TYPE : CHIP_NO_ERROR;
145#endif // INET_CONFIG_ENABLE_IPV4
146
147 case IPAddressType::kIPv6:
148 ip_addr_copy_from_ip6(outAddress, IPAddress::ToIPv6());
149#if INET_CONFIG_ENABLE_IPV4
150 return (addressType == IPAddressType::kIPv4) ? INET_ERROR_WRONG_ADDRESS_TYPE : CHIP_NO_ERROR;
151#else
152 return CHIP_NO_ERROR;
153#endif // INET_CONFIG_ENABLE_IPV4
154
155 case IPAddressType::kAny:
156#if INET_CONFIG_ENABLE_IPV4
157 if (addressType == IPAddressType::kIPv4)
158 {
159 outAddress = *IP4_ADDR_ANY;
160 return CHIP_NO_ERROR;
161 }
162#endif // INET_CONFIG_ENABLE_IPV4
163 outAddress = *IP6_ADDR_ANY;
164 return CHIP_NO_ERROR;
165
166 default:
167 return INET_ERROR_WRONG_ADDRESS_TYPE;
168 }
169}
170
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700171lwip_ip_addr_type IPAddress::ToLwIPAddrType(IPAddressType typ)
172{
173 lwip_ip_addr_type ret;
174
175 switch (typ)
176 {
177#if INET_CONFIG_ENABLE_IPV4
Kevin Schoedel77b06032021-10-21 09:15:11 -0400178 case IPAddressType::kIPv4:
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700179 ret = IPADDR_TYPE_V4;
180 break;
181#endif // INET_CONFIG_ENABLE_IPV4
182
Kevin Schoedel77b06032021-10-21 09:15:11 -0400183 case IPAddressType::kIPv6:
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700184 ret = IPADDR_TYPE_V6;
185 break;
186
187 default:
188 ret = IPADDR_TYPE_ANY;
189 break;
190 }
191
192 return ret;
193}
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700194
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700195ip6_addr_t IPAddress::ToIPv6() const
196{
Praveen Chandran31156c42021-12-01 09:35:03 -0800197 ip6_addr_t ipAddr = { 0 };
Praveen Chandrand5810e52021-11-02 20:04:00 -0700198 static_assert(sizeof(ipAddr.addr) == sizeof(Addr), "ip6_addr_t size mismatch");
199 memcpy(&ipAddr.addr, Addr, sizeof(ipAddr.addr));
Michael Spang679e92c2020-10-07 12:21:39 -0400200 return ipAddr;
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700201}
202
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700203#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
204
Vivien Nicolas79625962020-06-19 00:28:26 +0200205#if CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700206
207#if INET_CONFIG_ENABLE_IPV4
Kevin Schoedel33ca5222021-10-22 10:50:21 -0400208IPAddress::IPAddress(const struct in_addr & ipv4Addr)
209{
210 Addr[0] = 0;
211 Addr[1] = 0;
212 Addr[2] = htonl(0xFFFF);
213 Addr[3] = ipv4Addr.s_addr;
214}
215#endif // INET_CONFIG_ENABLE_IPV4
216
217IPAddress::IPAddress(const struct in6_addr & ipv6Addr)
218{
219 static_assert(sizeof(*this) == sizeof(ipv6Addr), "in6_addr size mismatch");
220 memcpy(Addr, &ipv6Addr, sizeof(ipv6Addr));
221}
222
223#if INET_CONFIG_ENABLE_IPV4
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700224struct in_addr IPAddress::ToIPv4() const
225{
226 struct in_addr ipv4Addr;
227 ipv4Addr.s_addr = Addr[3];
228 return ipv4Addr;
229}
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700230#endif // INET_CONFIG_ENABLE_IPV4
231
232struct in6_addr IPAddress::ToIPv6() const
233{
Michael Spang679e92c2020-10-07 12:21:39 -0400234 in6_addr ipAddr;
235 static_assert(sizeof(ipAddr) == sizeof(Addr), "in6_addr size mismatch");
236 memcpy(&ipAddr, Addr, sizeof(ipAddr));
237 return ipAddr;
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700238}
239
Boris Zbarskya3b40052023-05-11 21:20:54 -0400240CHIP_ERROR IPAddress::GetIPAddressFromSockAddr(const SockAddrWithoutStorage & sockaddr, IPAddress & outIPAddress)
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700241{
242#if INET_CONFIG_ENABLE_IPV4
Kevin Schoedel33ca5222021-10-22 10:50:21 -0400243 if (sockaddr.any.sa_family == AF_INET)
Kevin Schoedelf86f21f2021-12-16 07:17:46 -0500244 {
245 outIPAddress = FromSockAddr(sockaddr.in);
246 return CHIP_NO_ERROR;
247 }
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700248#endif // INET_CONFIG_ENABLE_IPV4
Kevin Schoedel33ca5222021-10-22 10:50:21 -0400249 if (sockaddr.any.sa_family == AF_INET6)
Kevin Schoedelf86f21f2021-12-16 07:17:46 -0500250 {
251 outIPAddress = FromSockAddr(sockaddr.in6);
252 return CHIP_NO_ERROR;
253 }
254 return INET_ERROR_WRONG_ADDRESS_TYPE;
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700255}
256
Vivien Nicolas79625962020-06-19 00:28:26 +0200257#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700258
Jean-Francois Penven75bdf792022-04-14 13:32:17 -0400259#if CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT
260IPAddress::IPAddress(const otIp6Address & ipv6Addr)
261{
262 static_assert(sizeof(ipv6Addr.mFields.m32) == sizeof(Addr), "otIp6Address size mismatch");
263 memcpy(Addr, ipv6Addr.mFields.m32, sizeof(Addr));
264}
265otIp6Address IPAddress::ToIPv6() const
266{
267 otIp6Address otAddr;
268 static_assert(sizeof(otAddr.mFields.m32) == sizeof(Addr), "otIp6Address size mismatch");
269 memcpy(otAddr.mFields.m32, Addr, sizeof(otAddr.mFields.m32));
270 return otAddr;
271}
272
Jean-Francois Penven9405c202022-05-03 15:37:44 -0400273IPAddress IPAddress::FromOtAddr(const otIp6Address & address)
Jean-Francois Penven75bdf792022-04-14 13:32:17 -0400274{
275 IPAddress addr;
276 static_assert(sizeof(address.mFields.m32) == sizeof(addr), "otIp6Address size mismatch");
277 memcpy(addr.Addr, address.mFields.m32, sizeof(addr.Addr));
278 return addr;
279}
280#endif // CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT
281
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700282// Is address an IPv4 address encoded in IPv6 format?
283bool IPAddress::IsIPv4() const
284{
285 return Addr[0] == 0 && Addr[1] == 0 && Addr[2] == htonl(0xFFFF);
286}
287
288// Is address a IPv4 multicast address?
Michael Spangb0e38c22020-09-30 14:20:50 -0400289bool IPAddress::IsIPv4Multicast() const
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700290{
291 return (IsIPv4() && ((ntohl(Addr[3]) & 0xF0000000U) == 0xE0000000U));
292}
293
294// Is address the IPv4 broadcast address?
Michael Spangb0e38c22020-09-30 14:20:50 -0400295bool IPAddress::IsIPv4Broadcast() const
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700296{
297 return (IsIPv4() && (Addr[3] == 0xFFFFFFFFU));
298}
299
300// Is address an IPv4 or IPv6 multicast address?
Michael Spangb0e38c22020-09-30 14:20:50 -0400301bool IPAddress::IsMulticast() const
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700302{
303 return (IsIPv6Multicast() || IsIPv4Multicast());
304}
305
Michael Spangb0e38c22020-09-30 14:20:50 -0400306bool IPAddress::IsIPv6() const
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700307{
308 return *this != Any && !IsIPv4();
309}
310
311// Is address an IPv6 multicast address?
Michael Spangb0e38c22020-09-30 14:20:50 -0400312bool IPAddress::IsIPv6Multicast() const
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700313{
314 return (ntohl(Addr[0]) & 0xFF000000U) == 0xFF000000U;
315}
316
317// Is address an IPv6 Global Unicast Address?
Michael Spangb0e38c22020-09-30 14:20:50 -0400318bool IPAddress::IsIPv6GlobalUnicast() const
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700319{
320 return (ntohl(Addr[0]) & 0xE0000000U) == 0x20000000U;
321}
322
323// Is address an IPv6 Unique Local Address?
324bool IPAddress::IsIPv6ULA() const
325{
326 return (ntohl(Addr[0]) & 0xFF000000U) == 0xFD000000U;
327}
328
329// Is address an IPv6 Link-local Address?
330bool IPAddress::IsIPv6LinkLocal() const
331{
332 return (Addr[0] == htonl(0xFE800000U) && Addr[1] == 0);
333}
334
335// Extract the interface id from a IPv6 ULA address. Returns 0 if the address
336// is not a ULA.
337uint64_t IPAddress::InterfaceId() const
338{
339 if (IsIPv6ULA())
Michael Spang181f0762020-10-05 22:20:52 -0400340 return ((static_cast<uint64_t>(ntohl(Addr[2]))) << 32) | (static_cast<uint64_t>(ntohl(Addr[3])));
Michael Spangf13b5232020-09-23 18:34:36 -0400341 return 0;
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700342}
343
344// Extract the subnet id from a IPv6 ULA address. Returns 0 if the address
345// is not a ULA.
346uint16_t IPAddress::Subnet() const
347{
348 if (IsIPv6ULA())
Michael Spang181f0762020-10-05 22:20:52 -0400349 return static_cast<uint16_t>(ntohl(Addr[1]));
Michael Spangf13b5232020-09-23 18:34:36 -0400350 return 0;
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700351}
352
353// Extract the global id from a IPv6 ULA address. Returns 0 if the address
354// is not a ULA.
355uint64_t IPAddress::GlobalId() const
356{
357 if (IsIPv6ULA())
Michael Spang181f0762020-10-05 22:20:52 -0400358 return ((static_cast<uint64_t>(ntohl(Addr[0]) & 0xFFFFFF)) << 16) |
359 (static_cast<uint64_t>(ntohl(Addr[1])) & 0xFFFF0000) >> 16;
Michael Spangf13b5232020-09-23 18:34:36 -0400360 return 0;
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700361}
362
363IPAddressType IPAddress::Type() const
364{
365 if (Addr[0] == 0 && Addr[1] == 0 && Addr[2] == 0 && Addr[3] == 0)
Kevin Schoedel77b06032021-10-21 09:15:11 -0400366 return IPAddressType::kAny;
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700367#if INET_CONFIG_ENABLE_IPV4
368 if (Addr[0] == 0 && Addr[1] == 0 && Addr[2] == htonl(0xFFFF))
Kevin Schoedel77b06032021-10-21 09:15:11 -0400369 return IPAddressType::kIPv4;
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700370#endif // INET_CONFIG_ENABLE_IPV4
Kevin Schoedel77b06032021-10-21 09:15:11 -0400371 return IPAddressType::kIPv6;
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700372}
373
374// Encode IPAddress to buffer in network byte order. Buffer must have at least 128 bits of available space.
375// Decoder must infer IP address type from context.
Rob Walker6f431212020-03-13 11:56:19 -0700376void IPAddress::WriteAddress(uint8_t *& p) const
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700377{
378 // Since each of the 32bit values in the Addr array is in network byte order, a simple
379 // memcpy of the entire array is sufficient while copying the address.
380
381 memcpy(p, &Addr[0], NL_INET_IPV6_ADDR_LEN_IN_BYTES);
382
383 p += NL_INET_IPV6_ADDR_LEN_IN_BYTES;
384}
385
386// Decode IPAddress from buffer in network byte order. Must infer IP address type from context.
Rob Walker6f431212020-03-13 11:56:19 -0700387void IPAddress::ReadAddress(const uint8_t *& p, IPAddress & output)
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700388{
389 // Since we want to store the address in the output array in network byte order, a simple
390 // memcpy of the entire array is used to retrieve from the buffer.
391
392 memcpy(&output.Addr[0], p, NL_INET_IPV6_ADDR_LEN_IN_BYTES);
393
394 p += NL_INET_IPV6_ADDR_LEN_IN_BYTES;
395}
396
397// Construct an IPv6 unique local address.
398IPAddress IPAddress::MakeULA(uint64_t globalId, uint16_t subnet, uint64_t interfaceId)
399{
400 IPAddress addr;
401
Michael Spang181f0762020-10-05 22:20:52 -0400402 addr.Addr[0] = 0xFD000000 | static_cast<uint32_t>((globalId & 0xFFFFFF0000ULL) >> 16);
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700403 addr.Addr[0] = htonl(addr.Addr[0]);
404
Michael Spang181f0762020-10-05 22:20:52 -0400405 addr.Addr[1] = static_cast<uint32_t>((globalId & 0x000000FFFFULL) << 16) | subnet;
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700406 addr.Addr[1] = htonl(addr.Addr[1]);
407
Michael Spang181f0762020-10-05 22:20:52 -0400408 addr.Addr[2] = htonl(static_cast<uint32_t>(interfaceId >> 32));
409 addr.Addr[3] = htonl(static_cast<uint32_t>(interfaceId));
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700410
411 return addr;
412}
413
414IPAddress IPAddress::MakeLLA(uint64_t interfaceId)
415{
416 IPAddress addr;
417
418 addr.Addr[0] = htonl(0xFE800000);
419 addr.Addr[1] = 0;
420
Michael Spang181f0762020-10-05 22:20:52 -0400421 addr.Addr[2] = htonl(static_cast<uint32_t>(interfaceId >> 32));
422 addr.Addr[3] = htonl(static_cast<uint32_t>(interfaceId));
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700423
424 return addr;
425}
426
Kevin Schoedel77b06032021-10-21 09:15:11 -0400427IPAddress IPAddress::MakeIPv6Multicast(IPv6MulticastFlags aFlags, uint8_t aScope,
Rob Walker6f431212020-03-13 11:56:19 -0700428 const uint8_t aGroupId[NL_INET_IPV6_MCAST_GROUP_LEN_IN_BYTES])
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700429{
Kevin Schoedel77b06032021-10-21 09:15:11 -0400430 const uint32_t lFlagsAndScope =
431 (((static_cast<uint32_t>(aFlags.Raw()) & 0xF) << 20) | ((static_cast<uint32_t>(aScope) & 0xF) << 16));
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700432 IPAddress addr;
433
Boris Zbarsky8e3186e2020-09-10 13:49:41 -0400434 addr.Addr[0] = htonl((0xFF000000U | lFlagsAndScope) | (uint32_t(aGroupId[0]) << 8) | (uint32_t(aGroupId[1]) << 0));
435 addr.Addr[1] = htonl((uint32_t(aGroupId[2]) << 24) | (uint32_t(aGroupId[3]) << 16) | (uint32_t(aGroupId[4]) << 8) |
436 (uint32_t(aGroupId[5]) << 0));
437 addr.Addr[2] = htonl((uint32_t(aGroupId[6]) << 24) | (uint32_t(aGroupId[7]) << 16) | (uint32_t(aGroupId[8]) << 8) |
438 (uint32_t(aGroupId[9]) << 0));
439 addr.Addr[3] = htonl((uint32_t(aGroupId[10]) << 24) | (uint32_t(aGroupId[11]) << 16) | (uint32_t(aGroupId[12]) << 8) |
440 (uint32_t(aGroupId[13]) << 0));
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700441
442 return addr;
443}
444
Kevin Schoedel77b06032021-10-21 09:15:11 -0400445IPAddress IPAddress::MakeIPv6Multicast(IPv6MulticastFlags aFlags, uint8_t aScope, uint32_t aGroupId)
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700446{
Rob Walker6f431212020-03-13 11:56:19 -0700447 const uint8_t lGroupId[NL_INET_IPV6_MCAST_GROUP_LEN_IN_BYTES] = { 0,
448 0,
449 0,
450 0,
451 0,
452 0,
453 0,
454 0,
455 0,
456 0,
Michael Spang181f0762020-10-05 22:20:52 -0400457 static_cast<uint8_t>((aGroupId & 0xFF000000U) >> 24),
458 static_cast<uint8_t>((aGroupId & 0x00FF0000U) >> 16),
459 static_cast<uint8_t>((aGroupId & 0x0000FF00U) >> 8),
460 static_cast<uint8_t>((aGroupId & 0x000000FFU) >> 0) };
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700461
462 return (MakeIPv6Multicast(aFlags, aScope, lGroupId));
463}
464
465IPAddress IPAddress::MakeIPv6WellKnownMulticast(uint8_t aScope, uint32_t aGroupId)
466{
Kevin Schoedel77b06032021-10-21 09:15:11 -0400467 constexpr IPv6MulticastFlags lFlags;
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700468
469 return (MakeIPv6Multicast(lFlags, aScope, aGroupId));
470}
471
Kevin Schoedel77b06032021-10-21 09:15:11 -0400472IPAddress IPAddress::MakeIPv6TransientMulticast(IPv6MulticastFlags aFlags, uint8_t aScope,
Rob Walker6f431212020-03-13 11:56:19 -0700473 const uint8_t aGroupId[NL_INET_IPV6_MCAST_GROUP_LEN_IN_BYTES])
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700474{
Kevin Schoedel77b06032021-10-21 09:15:11 -0400475 aFlags.Set(IPv6MulticastFlag::kTransient);
476 return (MakeIPv6Multicast(aFlags, aScope, aGroupId));
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700477}
478
Rob Walker6f431212020-03-13 11:56:19 -0700479IPAddress IPAddress::MakeIPv6PrefixMulticast(uint8_t aScope, uint8_t aPrefixLength, const uint64_t & aPrefix, uint32_t aGroupId)
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700480{
Rob Walker6f431212020-03-13 11:56:19 -0700481 const uint8_t lReserved = 0;
Kevin Schoedel77b06032021-10-21 09:15:11 -0400482 const IPv6MulticastFlags lFlags = IPv6MulticastFlag::kPrefix;
Rob Walker6f431212020-03-13 11:56:19 -0700483 const uint8_t lGroupId[NL_INET_IPV6_MCAST_GROUP_LEN_IN_BYTES] = { lReserved,
484 aPrefixLength,
Michael Spang181f0762020-10-05 22:20:52 -0400485 static_cast<uint8_t>((aPrefix & 0xFF00000000000000ULL) >> 56),
486 static_cast<uint8_t>((aPrefix & 0x00FF000000000000ULL) >> 48),
487 static_cast<uint8_t>((aPrefix & 0x0000FF0000000000ULL) >> 40),
488 static_cast<uint8_t>((aPrefix & 0x000000FF00000000ULL) >> 32),
489 static_cast<uint8_t>((aPrefix & 0x00000000FF000000ULL) >> 24),
490 static_cast<uint8_t>((aPrefix & 0x0000000000FF0000ULL) >> 16),
491 static_cast<uint8_t>((aPrefix & 0x000000000000FF00ULL) >> 8),
492 static_cast<uint8_t>((aPrefix & 0x00000000000000FFULL) >> 0),
493 static_cast<uint8_t>((aGroupId & 0xFF000000U) >> 24),
494 static_cast<uint8_t>((aGroupId & 0x00FF0000U) >> 16),
495 static_cast<uint8_t>((aGroupId & 0x0000FF00U) >> 8),
496 static_cast<uint8_t>((aGroupId & 0x000000FFU) >> 0) };
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700497
498 return (MakeIPv6TransientMulticast(lFlags, aScope, lGroupId));
499}
500
Michael Spangb0e38c22020-09-30 14:20:50 -0400501IPAddress IPAddress::MakeIPv4Broadcast()
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700502{
503 IPAddress ipAddr;
504 ipAddr.Addr[0] = 0;
505 ipAddr.Addr[1] = 0;
506 ipAddr.Addr[2] = htonl(0xFFFF);
507 ipAddr.Addr[3] = 0xFFFFFFFF;
508 return ipAddr;
509}
510
Andrei Litvin48c20432023-06-16 15:19:38 -0400511IPAddress IPAddress::Loopback(IPAddressType type)
512{
513 IPAddress address;
514#if INET_CONFIG_ENABLE_IPV4
515 if (type == IPAddressType::kIPv4)
516 {
517 address.Addr[0] = 0;
518 address.Addr[1] = 0;
519 address.Addr[2] = htonl(0xFFFF);
520 address.Addr[3] = htonl(0x7F000001);
521 }
522 else
523#endif
524 {
525 address.Addr[0] = 0;
526 address.Addr[1] = 0;
527 address.Addr[2] = 0;
528 address.Addr[3] = htonl(1);
529 }
530
531 return address;
532}
533
Pankaj Garg2efbcce2020-03-10 12:05:08 -0700534} // namespace Inet
535} // namespace chip