Coverage Report

Created: 2025-05-04 06:22

/src/openweave-core/src/inet/IPAddress.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *
3
 *    Copyright (c) 2019 Google LLC.
4
 *    Copyright (c) 2013-2018 Nest Labs, Inc.
5
 *    All rights reserved.
6
 *
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>nl::Inet::IPAddress</tt> and
23
 *      related enumerated constants. The Nest Inet Layer uses objects
24
 *      of this class to represent Internet protocol addresses of both
25
 *      IPv4 and IPv6 address families. (IPv4 addresses are stored
26
 *      internally in the V4COMPAT format, reserved for that purpose.)
27
 *
28
 */
29
30
#ifndef __STDC_LIMIT_MACROS
31
#define __STDC_LIMIT_MACROS
32
#endif
33
#include <stdint.h>
34
#include <string.h>
35
36
#include <Weave/Core/WeaveEncoding.h>
37
#include <InetLayer/InetLayer.h>
38
39
#include "arpa-inet-compatibility.h"
40
41
namespace nl {
42
namespace Inet {
43
44
IPAddress IPAddress::Any;
45
46
bool IPAddress::operator==(const IPAddress& other) const
47
0
{
48
0
    return Addr[0] == other.Addr[0] && Addr[1] == other.Addr[1] && Addr[2] == other.Addr[2] && Addr[3] == other.Addr[3];
49
0
}
50
51
bool IPAddress::operator!=(const IPAddress& other) const
52
0
{
53
0
    return Addr[0] != other.Addr[0] || Addr[1] != other.Addr[1] || Addr[2] != other.Addr[2] || Addr[3] != other.Addr[3];
54
0
}
55
56
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
57
58
#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5
59
ip_addr_t IPAddress::ToLwIPAddr(void) const
60
{
61
    ip_addr_t ret;
62
63
    switch (Type())
64
    {
65
#if INET_CONFIG_ENABLE_IPV4
66
    case kIPAddressType_IPv4:
67
        IP_SET_TYPE_VAL(ret, IPADDR_TYPE_V4);
68
        *ip_2_ip4(&ret) = IPAddress::ToIPv4();
69
        break;
70
#endif // INET_CONFIG_ENABLE_IPV4
71
72
    case kIPAddressType_IPv6:
73
        IP_SET_TYPE_VAL(ret, IPADDR_TYPE_V6);
74
        *ip_2_ip6(&ret) = IPAddress::ToIPv6();
75
        break;
76
77
    default:
78
        ret = *IP_ADDR_ANY;
79
        break;
80
    }
81
82
    return ret;
83
}
84
85
IPAddress IPAddress::FromLwIPAddr(const ip_addr_t &addr)
86
{
87
    IPAddress ret;
88
89
    switch (IP_GET_TYPE(&addr))
90
    {
91
#if INET_CONFIG_ENABLE_IPV4
92
    case IPADDR_TYPE_V4:
93
        ret = IPAddress::FromIPv4(*ip_2_ip4(&addr));
94
        break;
95
#endif // INET_CONFIG_ENABLE_IPV4
96
97
    case IPADDR_TYPE_V6:
98
        ret = IPAddress::FromIPv6(*ip_2_ip6(&addr));
99
        break;
100
101
    default:
102
        ret = Any;
103
        break;
104
    }
105
106
    return ret;
107
}
108
109
lwip_ip_addr_type IPAddress::ToLwIPAddrType(IPAddressType typ)
110
{
111
    lwip_ip_addr_type ret;
112
113
    switch (typ)
114
    {
115
#if INET_CONFIG_ENABLE_IPV4
116
    case kIPAddressType_IPv4:
117
        ret = IPADDR_TYPE_V4;
118
        break;
119
#endif // INET_CONFIG_ENABLE_IPV4
120
121
    case kIPAddressType_IPv6:
122
        ret = IPADDR_TYPE_V6;
123
        break;
124
125
    default:
126
        ret = IPADDR_TYPE_ANY;
127
        break;
128
    }
129
130
    return ret;
131
}
132
#endif // LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5
133
134
#if INET_CONFIG_ENABLE_IPV4
135
ip4_addr_t IPAddress::ToIPv4() const
136
{
137
    return *(ip4_addr_t *)&Addr[3];
138
}
139
140
IPAddress IPAddress::FromIPv4(const ip4_addr_t &ipv4Addr)
141
{
142
    IPAddress ipAddr;
143
    ipAddr.Addr[0] = 0;
144
    ipAddr.Addr[1] = 0;
145
    ipAddr.Addr[2] = htonl(0xFFFF);
146
    ipAddr.Addr[3] = ipv4Addr.addr;
147
    return ipAddr;
148
}
149
#endif // INET_CONFIG_ENABLE_IPV4
150
151
ip6_addr_t IPAddress::ToIPv6() const
152
{
153
    return *(ip6_addr_t *)Addr;
154
}
155
156
IPAddress IPAddress::FromIPv6(const ip6_addr_t &ipv6Addr)
157
{
158
    IPAddress ipAddr;
159
    ipAddr.Addr[0] = ipv6Addr.addr[0];
160
    ipAddr.Addr[1] = ipv6Addr.addr[1];
161
    ipAddr.Addr[2] = ipv6Addr.addr[2];
162
    ipAddr.Addr[3] = ipv6Addr.addr[3];
163
    return ipAddr;
164
}
165
166
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
167
168
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
169
170
#if INET_CONFIG_ENABLE_IPV4
171
struct in_addr IPAddress::ToIPv4() const
172
0
{
173
0
    struct in_addr ipv4Addr;
174
0
    ipv4Addr.s_addr = Addr[3];
175
0
    return ipv4Addr;
176
0
}
177
178
IPAddress IPAddress::FromIPv4(const struct in_addr &ipv4Addr)
179
0
{
180
0
    IPAddress ipAddr;
181
0
    ipAddr.Addr[0] = 0;
182
0
    ipAddr.Addr[1] = 0;
183
0
    ipAddr.Addr[2] = htonl(0xFFFF);
184
0
    ipAddr.Addr[3] = ipv4Addr.s_addr;
185
0
    return ipAddr;
186
0
}
187
#endif // INET_CONFIG_ENABLE_IPV4
188
189
struct in6_addr IPAddress::ToIPv6() const
190
0
{
191
0
    return *(struct in6_addr *) &Addr;
192
0
}
193
194
IPAddress IPAddress::FromIPv6(const struct in6_addr &ipv6Addr)
195
0
{
196
0
    IPAddress ipAddr;
197
0
    ipAddr.Addr[0] = htonl(((uint32_t)ipv6Addr.s6_addr[0])  << 24 |
198
0
                           ((uint32_t)ipv6Addr.s6_addr[1])  << 16 |
199
0
                           ((uint32_t)ipv6Addr.s6_addr[2])  << 8  |
200
0
                           ((uint32_t)ipv6Addr.s6_addr[3]));
201
0
    ipAddr.Addr[1] = htonl(((uint32_t)ipv6Addr.s6_addr[4])  << 24 |
202
0
                           ((uint32_t)ipv6Addr.s6_addr[5])  << 16 |
203
0
                           ((uint32_t)ipv6Addr.s6_addr[6])  << 8  |
204
0
                           ((uint32_t)ipv6Addr.s6_addr[7]));
205
0
    ipAddr.Addr[2] = htonl(((uint32_t)ipv6Addr.s6_addr[8])  << 24 |
206
0
                           ((uint32_t)ipv6Addr.s6_addr[9])  << 16 |
207
0
                           ((uint32_t)ipv6Addr.s6_addr[10]) << 8  |
208
0
                           ((uint32_t)ipv6Addr.s6_addr[11]));
209
0
    ipAddr.Addr[3] = htonl(((uint32_t)ipv6Addr.s6_addr[12]) << 24 |
210
0
                           ((uint32_t)ipv6Addr.s6_addr[13]) << 16 |
211
0
                           ((uint32_t)ipv6Addr.s6_addr[14]) << 8  |
212
0
                           ((uint32_t)ipv6Addr.s6_addr[15]));
213
0
    return ipAddr;
214
0
}
215
216
IPAddress IPAddress::FromSockAddr(const struct sockaddr& sockaddr)
217
0
{
218
0
#if INET_CONFIG_ENABLE_IPV4
219
0
    if (sockaddr.sa_family == AF_INET)
220
0
        return FromIPv4(((sockaddr_in *) &sockaddr)->sin_addr);
221
0
#endif // INET_CONFIG_ENABLE_IPV4
222
0
    if (sockaddr.sa_family == AF_INET6)
223
0
        return FromIPv6(((sockaddr_in6 *) &sockaddr)->sin6_addr);
224
0
    return Any;
225
0
}
226
227
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
228
229
// Is address an IPv4 address encoded in IPv6 format?
230
bool IPAddress::IsIPv4() const
231
0
{
232
0
    return Addr[0] == 0 && Addr[1] == 0 && Addr[2] == htonl(0xFFFF);
233
0
}
234
235
// Is address a IPv4 multicast address?
236
bool IPAddress::IsIPv4Multicast(void) const
237
0
{
238
0
    return (IsIPv4() && ((ntohl(Addr[3]) & 0xF0000000U) == 0xE0000000U));
239
0
}
240
241
// Is address the IPv4 broadcast address?
242
bool IPAddress::IsIPv4Broadcast(void) const
243
0
{
244
0
    return (IsIPv4() && (Addr[3] == 0xFFFFFFFFU));
245
0
}
246
247
// Is address an IPv4 or IPv6 multicast address?
248
bool IPAddress::IsMulticast(void) const
249
0
{
250
0
    return (IsIPv6Multicast() || IsIPv4Multicast());
251
0
}
252
253
bool IPAddress::IsIPv6(void) const
254
0
{
255
0
    return *this != Any && !IsIPv4();
256
0
}
257
258
// Is address an IPv6 multicast address?
259
bool IPAddress::IsIPv6Multicast(void) const
260
0
{
261
0
    return (ntohl(Addr[0]) & 0xFF000000U) == 0xFF000000U;
262
0
}
263
264
// Is address an IPv6 Global Unicast Address?
265
bool IPAddress::IsIPv6GlobalUnicast(void) const
266
0
{
267
0
    return (ntohl(Addr[0]) & 0xE0000000U) == 0x20000000U;
268
0
}
269
270
// Is address an IPv6 Unique Local Address?
271
bool IPAddress::IsIPv6ULA() const
272
0
{
273
0
    return (ntohl(Addr[0]) & 0xFF000000U) == 0xFD000000U;
274
0
}
275
276
// Is address an IPv6 Link-local Address?
277
bool IPAddress::IsIPv6LinkLocal() const
278
0
{
279
0
    return (Addr[0] == htonl(0xFE800000U) && Addr[1] == 0);
280
0
}
281
282
// Extract the interface id from a IPv6 ULA address.  Returns 0 if the address
283
// is not a ULA.
284
uint64_t IPAddress::InterfaceId() const
285
0
{
286
0
    if (IsIPv6ULA())
287
0
        return (((uint64_t) ntohl(Addr[2])) << 32) | ((uint64_t) ntohl(Addr[3]));
288
0
    else
289
0
        return 0;
290
0
}
291
292
// Extract the subnet id from a IPv6 ULA address.  Returns 0 if the address
293
// is not a ULA.
294
uint16_t IPAddress::Subnet() const
295
0
{
296
0
    if (IsIPv6ULA())
297
0
        return (uint16_t) ntohl(Addr[1]);
298
0
    else
299
0
        return 0;
300
0
}
301
302
// Extract the global id from a IPv6 ULA address.  Returns 0 if the address
303
// is not a ULA.
304
uint64_t IPAddress::GlobalId() const
305
0
{
306
0
    if (IsIPv6ULA())
307
0
        return (((uint64_t) (ntohl(Addr[0]) & 0xFFFFFF)) << 16) | ((uint64_t) (ntohl(Addr[1])) & 0xFFFF0000) >> 16;
308
0
    else
309
0
        return 0;
310
0
}
311
312
IPAddressType IPAddress::Type() const
313
0
{
314
0
    if (Addr[0] == 0 && Addr[1] == 0 && Addr[2] == 0 && Addr[3] == 0)
315
0
        return kIPAddressType_Any;
316
0
#if INET_CONFIG_ENABLE_IPV4
317
0
    if (Addr[0] == 0 && Addr[1] == 0 && Addr[2] == htonl(0xFFFF))
318
0
        return kIPAddressType_IPv4;
319
0
#endif // INET_CONFIG_ENABLE_IPV4
320
0
    return kIPAddressType_IPv6;
321
0
}
322
323
// Encode IPAddress to buffer in network byte order. Buffer must have at least 128 bits of available space.
324
// Decoder must infer IP address type from context.
325
void IPAddress::WriteAddress(uint8_t *&p) const
326
0
{
327
    // Since each of the 32bit values in the Addr array is in network byte order, a simple
328
    // memcpy of the entire array is sufficient while copying the address.
329
330
0
    memcpy(p, &Addr[0], NL_INET_IPV6_ADDR_LEN_IN_BYTES);
331
332
0
    p += NL_INET_IPV6_ADDR_LEN_IN_BYTES;
333
0
}
334
335
// Decode IPAddress from buffer in network byte order. Must infer IP address type from context.
336
void IPAddress::ReadAddress(const uint8_t *&p, IPAddress &output)
337
0
{
338
    // Since we want to store the address in the output array in network byte order, a simple
339
    // memcpy of the entire array is used to retrieve from the buffer.
340
341
0
    memcpy(&output.Addr[0], p, NL_INET_IPV6_ADDR_LEN_IN_BYTES);
342
343
0
    p += NL_INET_IPV6_ADDR_LEN_IN_BYTES;
344
0
}
345
346
// Construct an IPv6 unique local address.
347
IPAddress IPAddress::MakeULA(uint64_t globalId, uint16_t subnet, uint64_t interfaceId)
348
0
{
349
0
    IPAddress addr;
350
351
0
    addr.Addr[0] = 0xFD000000 | (uint32_t) ((globalId & 0xFFFFFF0000ULL) >> 16);
352
0
    addr.Addr[0] = htonl(addr.Addr[0]);
353
354
0
    addr.Addr[1] = (uint32_t) ((globalId & 0x000000FFFFULL) << 16) | subnet;
355
0
    addr.Addr[1] = htonl(addr.Addr[1]);
356
357
0
    addr.Addr[2] = htonl((uint32_t) (interfaceId >> 32));
358
0
    addr.Addr[3] = htonl((uint32_t) (interfaceId));
359
360
0
    return addr;
361
0
}
362
363
IPAddress IPAddress::MakeLLA(uint64_t interfaceId)
364
0
{
365
0
    IPAddress addr;
366
367
0
    addr.Addr[0] = htonl(0xFE800000);
368
0
    addr.Addr[1] = 0;
369
370
0
    addr.Addr[2] = htonl((uint32_t) (interfaceId >> 32));
371
0
    addr.Addr[3] = htonl((uint32_t) (interfaceId));
372
373
0
    return addr;
374
0
}
375
376
IPAddress IPAddress::MakeIPv6Multicast(uint8_t aFlags, uint8_t aScope, const uint8_t aGroupId[NL_INET_IPV6_MCAST_GROUP_LEN_IN_BYTES])
377
0
{
378
0
    const uint32_t lFlagsAndScope = (((aFlags & 0xF) << 20) |
379
0
                                     ((aScope & 0xF) << 16));
380
0
    IPAddress addr;
381
382
0
    addr.Addr[0] = htonl((0xFF000000U | lFlagsAndScope) |
383
0
                         (aGroupId[ 0] <<  8) |
384
0
                         (aGroupId[ 1] <<  0));
385
0
    addr.Addr[1] = htonl((aGroupId[ 2] << 24) |
386
0
                         (aGroupId[ 3] << 16) |
387
0
                         (aGroupId[ 4] <<  8) |
388
0
                         (aGroupId[ 5] <<  0));
389
0
    addr.Addr[2] = htonl((aGroupId[ 6] << 24) |
390
0
                         (aGroupId[ 7] << 16) |
391
0
                         (aGroupId[ 8] <<  8) |
392
0
                         (aGroupId[ 9] <<  0));
393
0
    addr.Addr[3] = htonl((aGroupId[10] << 24) |
394
0
                         (aGroupId[11] << 16) |
395
0
                         (aGroupId[12] <<  8) |
396
0
                         (aGroupId[13] <<  0));
397
398
0
    return addr;
399
0
}
400
401
IPAddress IPAddress::MakeIPv6Multicast(uint8_t aFlags, uint8_t aScope, uint32_t aGroupId)
402
0
{
403
0
    const uint8_t lGroupId[NL_INET_IPV6_MCAST_GROUP_LEN_IN_BYTES] =
404
0
    {
405
0
        0, 0, 0, 0, 0, 0, 0,
406
0
        0, 0, 0,
407
0
        (uint8_t)((aGroupId & 0xFF000000U) >> 24),
408
0
        (uint8_t)((aGroupId & 0x00FF0000U) >> 16),
409
0
        (uint8_t)((aGroupId & 0x0000FF00U) >>  8),
410
0
        (uint8_t)((aGroupId & 0x000000FFU) >>  0)
411
0
    };
412
413
0
    return (MakeIPv6Multicast(aFlags, aScope, lGroupId));
414
0
}
415
416
IPAddress IPAddress::MakeIPv6WellKnownMulticast(uint8_t aScope, uint32_t aGroupId)
417
0
{
418
0
    const uint8_t lFlags = 0;
419
420
0
    return (MakeIPv6Multicast(lFlags, aScope, aGroupId));
421
0
}
422
423
IPAddress IPAddress::MakeIPv6TransientMulticast(uint8_t aFlags, uint8_t aScope, const uint8_t aGroupId[NL_INET_IPV6_MCAST_GROUP_LEN_IN_BYTES])
424
0
{
425
0
    const uint8_t lFlags = (aFlags | kIPv6MulticastFlag_Transient);
426
427
0
    return (MakeIPv6Multicast(lFlags, aScope, aGroupId));
428
0
}
429
430
IPAddress IPAddress::MakeIPv6PrefixMulticast(uint8_t aScope, uint8_t aPrefixLength, const uint64_t &aPrefix, uint32_t aGroupId)
431
0
{
432
0
    const uint8_t lReserved    = 0;
433
0
    const uint8_t lFlags       = kIPv6MulticastFlag_Prefix;
434
0
    const uint8_t lGroupId[NL_INET_IPV6_MCAST_GROUP_LEN_IN_BYTES] =
435
0
    {
436
0
        lReserved,
437
0
        aPrefixLength,
438
0
        (uint8_t)((aPrefix  & 0xFF00000000000000ULL) >> 56),
439
0
        (uint8_t)((aPrefix  & 0x00FF000000000000ULL) >> 48),
440
0
        (uint8_t)((aPrefix  & 0x0000FF0000000000ULL) >> 40),
441
0
        (uint8_t)((aPrefix  & 0x000000FF00000000ULL) >> 32),
442
0
        (uint8_t)((aPrefix  & 0x00000000FF000000ULL) >> 24),
443
0
        (uint8_t)((aPrefix  & 0x0000000000FF0000ULL) >> 16),
444
0
        (uint8_t)((aPrefix  & 0x000000000000FF00ULL) >>  8),
445
0
        (uint8_t)((aPrefix  & 0x00000000000000FFULL) >>  0),
446
0
        (uint8_t)((aGroupId & 0xFF000000U)           >> 24),
447
0
        (uint8_t)((aGroupId & 0x00FF0000U)           >> 16),
448
0
        (uint8_t)((aGroupId & 0x0000FF00U)           >>  8),
449
0
        (uint8_t)((aGroupId & 0x000000FFU)           >>  0)
450
0
    };
451
452
0
    return (MakeIPv6TransientMulticast(lFlags, aScope, lGroupId));
453
0
}
454
455
IPAddress IPAddress::MakeIPv4Broadcast(void)
456
0
{
457
0
    IPAddress ipAddr;
458
0
    ipAddr.Addr[0] = 0;
459
0
    ipAddr.Addr[1] = 0;
460
0
    ipAddr.Addr[2] = htonl(0xFFFF);
461
0
    ipAddr.Addr[3] = 0xFFFFFFFF;
462
0
    return ipAddr;
463
0
}
464
465
466
} // namespace Inet
467
} // namespace nl