]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/in-addr-util.c
analyze: fix typo
[thirdparty/systemd.git] / src / basic / in-addr-util.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
3b653205
LP
2
3#include <arpa/inet.h>
11c3a366 4#include <endian.h>
ca78ad1d 5#include <stdio.h>
3b653205 6
b5efdb8a 7#include "alloc-util.h"
66855de7 8#include "errno-util.h"
0c15577a 9#include "hash-funcs.h"
3b653205 10#include "in-addr-util.h"
3ae6b3bf 11#include "logarithm.h"
d559f463 12#include "memory-util.h"
2817157b 13#include "parse-util.h"
c5236acd 14#include "random-util.h"
0c15577a 15#include "siphash24.h"
c71384a9 16#include "stdio-util.h"
a723fb85 17#include "string-util.h"
3b653205 18
34380032 19bool in4_addr_is_null(const struct in_addr *a) {
fdedbe26 20 assert(a);
34380032 21
fdedbe26 22 return a->s_addr == 0;
34380032
LP
23}
24
7653dcc3
YW
25bool in6_addr_is_null(const struct in6_addr *a) {
26 assert(a);
27
a8a39e23 28 return eqzero(a->s6_addr32);
7653dcc3
YW
29}
30
af93291c 31int in_addr_is_null(int family, const union in_addr_union *u) {
3b653205
LP
32 assert(u);
33
34 if (family == AF_INET)
34380032 35 return in4_addr_is_null(&u->in);
3b653205
LP
36
37 if (family == AF_INET6)
7653dcc3 38 return in6_addr_is_null(&u->in6);
3b653205
LP
39
40 return -EAFNOSUPPORT;
41}
42
fdedbe26
LP
43bool in4_addr_is_link_local(const struct in_addr *a) {
44 assert(a);
45
46 return (be32toh(a->s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
47}
48
d3efcd2d
YW
49bool in4_addr_is_link_local_dynamic(const struct in_addr *a) {
50 assert(a);
51
52 if (!in4_addr_is_link_local(a))
53 return false;
54
55 /* 169.254.0.0/24 and 169.254.255.0/24 must not be used for the dynamic IPv4LL assignment.
56 * See RFC 3927 Section 2.1:
57 * The IPv4 prefix 169.254/16 is registered with the IANA for this purpose. The first 256 and last
58 * 256 addresses in the 169.254/16 prefix are reserved for future use and MUST NOT be selected by a
59 * host using this dynamic configuration mechanism. */
60 return !IN_SET(be32toh(a->s_addr) & 0x0000FF00U, 0x0000U, 0xFF00U);
61}
62
1235befa
YW
63bool in6_addr_is_link_local(const struct in6_addr *a) {
64 assert(a);
65
a8a39e23 66 return (a->s6_addr32[0] & htobe32(0xffc00000)) == htobe32(0xfe800000);
1235befa
YW
67}
68
af93291c
LP
69int in_addr_is_link_local(int family, const union in_addr_union *u) {
70 assert(u);
71
72 if (family == AF_INET)
fdedbe26 73 return in4_addr_is_link_local(&u->in);
af93291c
LP
74
75 if (family == AF_INET6)
1235befa 76 return in6_addr_is_link_local(&u->in6);
af93291c
LP
77
78 return -EAFNOSUPPORT;
79}
3b653205 80
5643cfc0
YW
81bool in6_addr_is_link_local_all_nodes(const struct in6_addr *a) {
82 assert(a);
83
84 /* ff02::1 */
85 return be32toh(a->s6_addr32[0]) == UINT32_C(0xff020000) &&
86 a->s6_addr32[1] == 0 &&
87 a->s6_addr32[2] == 0 &&
88 be32toh(a->s6_addr32[3]) == UINT32_C(0x00000001);
89}
90
c7f46150
YW
91bool in4_addr_is_multicast(const struct in_addr *a) {
92 assert(a);
93
94 return IN_MULTICAST(be32toh(a->s_addr));
95}
96
97bool in6_addr_is_multicast(const struct in6_addr *a) {
98 assert(a);
99
a8a39e23 100 return a->s6_addr[0] == 0xff;
c7f46150
YW
101}
102
85257f48
SS
103int in_addr_is_multicast(int family, const union in_addr_union *u) {
104 assert(u);
105
106 if (family == AF_INET)
c7f46150 107 return in4_addr_is_multicast(&u->in);
85257f48
SS
108
109 if (family == AF_INET6)
c7f46150 110 return in6_addr_is_multicast(&u->in6);
85257f48
SS
111
112 return -EAFNOSUPPORT;
113}
114
ccea2448
YW
115bool in4_addr_is_local_multicast(const struct in_addr *a) {
116 assert(a);
117
118 return (be32toh(a->s_addr) & UINT32_C(0xffffff00)) == UINT32_C(0xe0000000);
119}
120
fdedbe26
LP
121bool in4_addr_is_localhost(const struct in_addr *a) {
122 assert(a);
123
124 /* All of 127.x.x.x is localhost. */
125 return (be32toh(a->s_addr) & UINT32_C(0xFF000000)) == UINT32_C(127) << 24;
126}
127
072320ea
TH
128bool in4_addr_is_non_local(const struct in_addr *a) {
129 /* Whether the address is not null and not localhost.
130 *
131 * As such, it is suitable to configure as DNS/NTP server from DHCP. */
132 return !in4_addr_is_null(a) &&
133 !in4_addr_is_localhost(a);
134}
135
d559f463
DDM
136static bool in6_addr_is_loopback(const struct in6_addr *a) {
137 return memcmp(a, &(struct in6_addr) IN6ADDR_LOOPBACK_INIT, sizeof(struct in6_addr)) == 0;
138}
139
d830ebbd
LP
140int in_addr_is_localhost(int family, const union in_addr_union *u) {
141 assert(u);
142
143 if (family == AF_INET)
fdedbe26 144 return in4_addr_is_localhost(&u->in);
d830ebbd 145
db15affc 146 if (family == AF_INET6)
d559f463 147 return in6_addr_is_loopback(&u->in6);
d830ebbd
LP
148
149 return -EAFNOSUPPORT;
150}
151
b69bfa43
YW
152int in_addr_is_localhost_one(int family, const union in_addr_union *u) {
153 assert(u);
154
155 if (family == AF_INET)
156 /* 127.0.0.1 */
157 return be32toh(u->in.s_addr) == UINT32_C(0x7F000001);
158
159 if (family == AF_INET6)
d559f463 160 return in6_addr_is_loopback(&u->in6);
b69bfa43
YW
161
162 return -EAFNOSUPPORT;
163}
164
c3e96088
YW
165bool in6_addr_is_ipv4_mapped_address(const struct in6_addr *a) {
166 return a->s6_addr32[0] == 0 &&
167 a->s6_addr32[1] == 0 &&
168 a->s6_addr32[2] == htobe32(UINT32_C(0x0000ffff));
169}
170
9a897e22
YW
171bool in4_addr_equal(const struct in_addr *a, const struct in_addr *b) {
172 assert(a);
173 assert(b);
174
175 return a->s_addr == b->s_addr;
176}
177
fa550434
YW
178bool in6_addr_equal(const struct in6_addr *a, const struct in6_addr *b) {
179 assert(a);
180 assert(b);
181
d559f463 182 return memcmp(a, b, sizeof(struct in6_addr)) == 0;
fa550434
YW
183}
184
623a4c97 185int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b) {
3b653205
LP
186 assert(a);
187 assert(b);
188
189 if (family == AF_INET)
9a897e22 190 return in4_addr_equal(&a->in, &b->in);
3b653205
LP
191
192 if (family == AF_INET6)
fa550434 193 return in6_addr_equal(&a->in6, &b->in6);
3b653205
LP
194
195 return -EAFNOSUPPORT;
196}
197
21ae0b4b
YW
198bool in4_addr_prefix_intersect(
199 const struct in_addr *a,
3b653205 200 unsigned aprefixlen,
21ae0b4b 201 const struct in_addr *b,
3b653205
LP
202 unsigned bprefixlen) {
203
3b653205
LP
204 assert(a);
205 assert(b);
206
21ae0b4b
YW
207 unsigned m = MIN3(aprefixlen, bprefixlen, (unsigned) (sizeof(struct in_addr) * 8));
208 if (m == 0)
209 return true; /* Let's return earlier, to avoid shift by 32. */
3b653205 210
21ae0b4b
YW
211 uint32_t x = be32toh(a->s_addr ^ b->s_addr);
212 uint32_t n = 0xFFFFFFFFUL << (32 - m);
213 return (x & n) == 0;
214}
3b653205 215
21ae0b4b
YW
216bool in6_addr_prefix_intersect(
217 const struct in6_addr *a,
218 unsigned aprefixlen,
219 const struct in6_addr *b,
220 unsigned bprefixlen) {
3b653205 221
21ae0b4b
YW
222 assert(a);
223 assert(b);
3b653205 224
21ae0b4b
YW
225 unsigned m = MIN3(aprefixlen, bprefixlen, (unsigned) (sizeof(struct in6_addr) * 8));
226 if (m == 0)
227 return true;
3b653205 228
21ae0b4b
YW
229 for (size_t i = 0; i < sizeof(struct in6_addr); i++) {
230 uint8_t x = a->s6_addr[i] ^ b->s6_addr[i];
231 uint8_t n = m < 8 ? (0xFF << (8 - m)) : 0xFF;
232 if ((x & n) != 0)
233 return false;
3b653205 234
21ae0b4b
YW
235 if (m <= 8)
236 break;
3b653205 237
21ae0b4b
YW
238 m -= 8;
239 }
3b653205 240
21ae0b4b
YW
241 return true;
242}
3b653205 243
21ae0b4b
YW
244int in_addr_prefix_intersect(
245 int family,
246 const union in_addr_union *a,
247 unsigned aprefixlen,
248 const union in_addr_union *b,
249 unsigned bprefixlen) {
3b653205 250
21ae0b4b
YW
251 assert(a);
252 assert(b);
3b653205 253
21ae0b4b 254 /* Checks whether there are any addresses that are in both networks. */
3b653205 255
21ae0b4b
YW
256 if (family == AF_INET)
257 return in4_addr_prefix_intersect(&a->in, aprefixlen, &b->in, bprefixlen);
258
259 if (family == AF_INET6)
260 return in6_addr_prefix_intersect(&a->in6, aprefixlen, &b->in6, bprefixlen);
3b653205
LP
261
262 return -EAFNOSUPPORT;
263}
264
0dd25fb9 265int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen) {
3b653205
LP
266 assert(u);
267
518b6da5
YW
268 /* Increases the network part of an address by one. Returns 0 if that succeeds, or -ERANGE if
269 * this overflows. */
3b653205 270
171f625b 271 return in_addr_prefix_nth(family, u, prefixlen, 1);
c5236acd
YW
272}
273
863b99cd
AR
274/*
275 * Calculates the nth prefix of size prefixlen starting from the address denoted by u.
276 *
518b6da5 277 * On success 0 will be returned and the calculated prefix will be available in
9164338b 278 * u. In case the calculation cannot be performed (invalid prefix length,
863b99cd
AR
279 * overflows would occur) -ERANGE is returned. If the address family given isn't
280 * supported -EAFNOSUPPORT will be returned.
281 *
863b99cd 282 * Examples:
518b6da5
YW
283 * - in_addr_prefix_nth(AF_INET, 192.168.0.0, 24, 2), returns 0, writes 192.168.2.0 to u
284 * - in_addr_prefix_nth(AF_INET, 192.168.0.0, 24, 0), returns 0, no data written
863b99cd
AR
285 * - in_addr_prefix_nth(AF_INET, 255.255.255.0, 24, 1), returns -ERANGE, no data written
286 * - in_addr_prefix_nth(AF_INET, 255.255.255.0, 0, 1), returns -ERANGE, no data written
518b6da5 287 * - in_addr_prefix_nth(AF_INET6, 2001:db8, 64, 0xff00) returns 0, writes 2001:0db8:0000:ff00:: to u
863b99cd
AR
288 */
289int in_addr_prefix_nth(int family, union in_addr_union *u, unsigned prefixlen, uint64_t nth) {
290 assert(u);
291
292 if (prefixlen <= 0)
293 return -ERANGE;
294
863b99cd
AR
295 if (family == AF_INET) {
296 uint32_t c, n, t;
7b6b05cf 297
863b99cd 298 if (prefixlen > 32)
7b6b05cf 299 return -ERANGE;
863b99cd
AR
300
301 c = be32toh(u->in.s_addr);
302
303 t = nth << (32 - prefixlen);
304
305 /* Check for wrap */
306 if (c > UINT32_MAX - t)
307 return -ERANGE;
308
309 n = c + t;
310
311 n &= UINT32_C(0xFFFFFFFF) << (32 - prefixlen);
312 u->in.s_addr = htobe32(n);
518b6da5 313 return 0;
863b99cd
AR
314 }
315
316 if (family == AF_INET6) {
9164338b 317 bool overflow = false;
863b99cd
AR
318
319 if (prefixlen > 128)
7b6b05cf 320 return -ERANGE;
863b99cd 321
863b99cd 322 for (unsigned i = 16; i > 0; i--) {
9164338b
YW
323 unsigned t, j = i - 1, p = j * 8;
324
325 if (p >= prefixlen) {
326 u->in6.s6_addr[j] = 0;
327 continue;
328 }
329
330 if (prefixlen - p < 8) {
331 u->in6.s6_addr[j] &= 0xff << (8 - (prefixlen - p));
332 t = u->in6.s6_addr[j] + ((nth & 0xff) << (8 - (prefixlen - p)));
333 nth >>= prefixlen - p;
334 } else {
335 t = u->in6.s6_addr[j] + (nth & 0xff) + overflow;
336 nth >>= 8;
337 }
338
339 overflow = t > UINT8_MAX;
340 u->in6.s6_addr[j] = (uint8_t) (t & 0xff);
863b99cd
AR
341 }
342
9164338b 343 if (overflow || nth != 0)
863b99cd
AR
344 return -ERANGE;
345
518b6da5 346 return 0;
863b99cd
AR
347 }
348
349 return -EAFNOSUPPORT;
350}
351
c5236acd
YW
352int in_addr_random_prefix(
353 int family,
354 union in_addr_union *u,
355 unsigned prefixlen_fixed_part,
356 unsigned prefixlen) {
357
358 assert(u);
359
360 /* Random network part of an address by one. */
361
362 if (prefixlen <= 0)
363 return 0;
364
365 if (family == AF_INET) {
366 uint32_t c, n;
367
368 if (prefixlen_fixed_part > 32)
369 prefixlen_fixed_part = 32;
370 if (prefixlen > 32)
371 prefixlen = 32;
372 if (prefixlen_fixed_part >= prefixlen)
373 return -EINVAL;
374
375 c = be32toh(u->in.s_addr);
376 c &= ((UINT32_C(1) << prefixlen_fixed_part) - 1) << (32 - prefixlen_fixed_part);
377
378 random_bytes(&n, sizeof(n));
379 n &= ((UINT32_C(1) << (prefixlen - prefixlen_fixed_part)) - 1) << (32 - prefixlen);
380
381 u->in.s_addr = htobe32(n | c);
382 return 1;
383 }
384
385 if (family == AF_INET6) {
386 struct in6_addr n;
387 unsigned i, j;
388
389 if (prefixlen_fixed_part > 128)
390 prefixlen_fixed_part = 128;
391 if (prefixlen > 128)
392 prefixlen = 128;
393 if (prefixlen_fixed_part >= prefixlen)
394 return -EINVAL;
395
396 random_bytes(&n, sizeof(n));
397
398 for (i = 0; i < 16; i++) {
399 uint8_t mask_fixed_part = 0, mask = 0;
400
401 if (i < (prefixlen_fixed_part + 7) / 8) {
402 if (i < prefixlen_fixed_part / 8)
403 mask_fixed_part = 0xffu;
404 else {
405 j = prefixlen_fixed_part % 8;
406 mask_fixed_part = ((UINT8_C(1) << (j + 1)) - 1) << (8 - j);
407 }
408 }
409
410 if (i < (prefixlen + 7) / 8) {
411 if (i < prefixlen / 8)
412 mask = 0xffu ^ mask_fixed_part;
413 else {
414 j = prefixlen % 8;
415 mask = (((UINT8_C(1) << (j + 1)) - 1) << (8 - j)) ^ mask_fixed_part;
416 }
417 }
418
419 u->in6.s6_addr[i] &= mask_fixed_part;
420 u->in6.s6_addr[i] |= n.s6_addr[i] & mask;
421 }
422
423 return 1;
424 }
3b653205
LP
425
426 return -EAFNOSUPPORT;
427}
428
1534c579
YW
429int in_addr_prefix_range(
430 int family,
431 const union in_addr_union *in,
432 unsigned prefixlen,
433 union in_addr_union *ret_start,
434 union in_addr_union *ret_end) {
435
436 union in_addr_union start, end;
437 int r;
438
439 assert(in);
440
441 if (!IN_SET(family, AF_INET, AF_INET6))
442 return -EAFNOSUPPORT;
443
444 if (ret_start) {
445 start = *in;
446 r = in_addr_prefix_nth(family, &start, prefixlen, 0);
447 if (r < 0)
448 return r;
449 }
450
451 if (ret_end) {
452 end = *in;
453 r = in_addr_prefix_nth(family, &end, prefixlen, 1);
454 if (r < 0)
455 return r;
456 }
457
458 if (ret_start)
459 *ret_start = start;
460 if (ret_end)
461 *ret_end = end;
462
463 return 0;
464}
465
0dd25fb9 466int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
81260be1 467 _cleanup_free_ char *x = NULL;
3b653205
LP
468 size_t l;
469
470 assert(u);
471 assert(ret);
472
473 if (family == AF_INET)
474 l = INET_ADDRSTRLEN;
475 else if (family == AF_INET6)
476 l = INET6_ADDRSTRLEN;
477 else
478 return -EAFNOSUPPORT;
479
480 x = new(char, l);
481 if (!x)
482 return -ENOMEM;
483
484 errno = 0;
84dbb3fd 485 if (!typesafe_inet_ntop(family, u, x, l))
66855de7 486 return errno_or_else(EINVAL);
3b653205 487
81260be1 488 *ret = TAKE_PTR(x);
3b653205
LP
489 return 0;
490}
491
0c15577a
DDM
492const char* typesafe_inet_ntop(int family, const union in_addr_union *a, char *buf, size_t len) {
493 return inet_ntop(family, a, buf, len);
494}
495
496const char* typesafe_inet_ntop4(const struct in_addr *a, char *buf, size_t len) {
497 return inet_ntop(AF_INET, a, buf, len);
498}
499
500const char* typesafe_inet_ntop6(const struct in6_addr *a, char *buf, size_t len) {
501 return inet_ntop(AF_INET6, a, buf, len);
502}
503
c71384a9
ZJS
504int in_addr_prefix_to_string(
505 int family,
506 const union in_addr_union *u,
507 unsigned prefixlen,
508 char *buf,
509 size_t buf_len) {
d9143dac
YW
510
511 assert(u);
c71384a9 512 assert(buf);
d9143dac 513
c71384a9 514 if (!IN_SET(family, AF_INET, AF_INET6))
d9143dac
YW
515 return -EAFNOSUPPORT;
516
d9143dac 517 errno = 0;
c71384a9
ZJS
518 if (!typesafe_inet_ntop(family, u, buf, buf_len))
519 return errno_or_else(ENOSPC);
d9143dac 520
c71384a9
ZJS
521 size_t l = strlen(buf);
522 if (!snprintf_ok(buf + l, buf_len - l, "/%u", prefixlen))
523 return -ENOSPC;
d9143dac
YW
524 return 0;
525}
526
a723fb85
YW
527int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret) {
528 _cleanup_free_ char *ip_str = NULL, *x = NULL;
529 int r;
530
531 assert(IN_SET(family, AF_INET, AF_INET6));
532 assert(u);
533 assert(ret);
534
535 /* Much like in_addr_to_string(), but optionally appends the zone interface index to the address, to properly
536 * handle IPv6 link-local addresses. */
537
538 r = in_addr_to_string(family, u, &ip_str);
539 if (r < 0)
540 return r;
541
542 if (family == AF_INET6) {
543 r = in_addr_is_link_local(family, u);
544 if (r < 0)
545 return r;
546 if (r == 0)
547 ifindex = 0;
548 } else
549 ifindex = 0; /* For IPv4 address, ifindex is always ignored. */
550
551 if (port == 0 && ifindex == 0 && isempty(server_name)) {
552 *ret = TAKE_PTR(ip_str);
553 return 0;
554 }
555
556 const char *separator = isempty(server_name) ? "" : "#";
557 server_name = strempty(server_name);
558
559 if (port > 0) {
560 if (family == AF_INET6) {
561 if (ifindex > 0)
562 r = asprintf(&x, "[%s]:%"PRIu16"%%%i%s%s", ip_str, port, ifindex, separator, server_name);
563 else
564 r = asprintf(&x, "[%s]:%"PRIu16"%s%s", ip_str, port, separator, server_name);
565 } else
566 r = asprintf(&x, "%s:%"PRIu16"%s%s", ip_str, port, separator, server_name);
567 } else {
568 if (ifindex > 0)
569 r = asprintf(&x, "%s%%%i%s%s", ip_str, ifindex, separator, server_name);
570 else {
571 x = strjoin(ip_str, separator, server_name);
572 r = x ? 0 : -ENOMEM;
573 }
574 }
575 if (r < 0)
576 return -ENOMEM;
577
578 *ret = TAKE_PTR(x);
579 return 0;
580}
581
0dd25fb9 582int in_addr_from_string(int family, const char *s, union in_addr_union *ret) {
fd18634d 583 union in_addr_union buffer;
3b653205 584 assert(s);
3b653205
LP
585
586 if (!IN_SET(family, AF_INET, AF_INET6))
587 return -EAFNOSUPPORT;
588
589 errno = 0;
fd18634d 590 if (inet_pton(family, s, ret ?: &buffer) <= 0)
66855de7 591 return errno_or_else(EINVAL);
3b653205
LP
592
593 return 0;
594}
74b2466e 595
4e2d5273 596int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret) {
74b2466e
LP
597 int r;
598
599 assert(s);
74b2466e
LP
600
601 r = in_addr_from_string(AF_INET, s, ret);
602 if (r >= 0) {
4e2d5273
LP
603 if (ret_family)
604 *ret_family = AF_INET;
74b2466e
LP
605 return 0;
606 }
607
608 r = in_addr_from_string(AF_INET6, s, ret);
609 if (r >= 0) {
4e2d5273
LP
610 if (ret_family)
611 *ret_family = AF_INET6;
74b2466e
LP
612 return 0;
613 }
614
615 return -EINVAL;
616}
44e7b949 617
5a941f5f 618unsigned char in4_addr_netmask_to_prefixlen(const struct in_addr *addr) {
44e7b949
LP
619 assert(addr);
620
1a359852 621 return 32U - u32ctz(be32toh(addr->s_addr));
44e7b949 622}
df40eee8 623
3f36b9ed 624/* Calculate an IPv4 netmask from prefix length, for example /8 -> 255.0.0.0. */
5a941f5f 625struct in_addr* in4_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char prefixlen) {
76917807
LP
626 assert(addr);
627 assert(prefixlen <= 32);
628
629 /* Shifting beyond 32 is not defined, handle this specially. */
630 if (prefixlen == 0)
631 addr->s_addr = 0;
632 else
633 addr->s_addr = htobe32((0xffffffff << (32 - prefixlen)) & 0xffffffff);
634
635 return addr;
636}
637
3f36b9ed
TM
638/* Calculate an IPv6 netmask from prefix length, for example /16 -> ffff::. */
639struct in6_addr* in6_addr_prefixlen_to_netmask(struct in6_addr *addr, unsigned char prefixlen) {
640 assert(addr);
641 assert(prefixlen <= 128);
642
643 for (unsigned i = 0; i < 16; i++) {
644 uint8_t mask;
645
646 if (prefixlen >= 8) {
647 mask = 0xFF;
648 prefixlen -= 8;
649 } else if (prefixlen > 0) {
650 mask = 0xFF << (8 - prefixlen);
651 prefixlen = 0;
652 } else {
653 assert(prefixlen == 0);
654 mask = 0;
655 }
656
657 addr->s6_addr[i] = mask;
658 }
659
660 return addr;
661}
662
663/* Calculate an IPv4 or IPv6 netmask from prefix length, for example /8 -> 255.0.0.0 or /16 -> ffff::. */
664int in_addr_prefixlen_to_netmask(int family, union in_addr_union *addr, unsigned char prefixlen) {
665 assert(addr);
666
667 switch (family) {
668 case AF_INET:
669 in4_addr_prefixlen_to_netmask(&addr->in, prefixlen);
670 return 0;
671 case AF_INET6:
672 in6_addr_prefixlen_to_netmask(&addr->in6, prefixlen);
673 return 0;
674 default:
675 return -EAFNOSUPPORT;
676 }
677}
678
5a941f5f 679int in4_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen) {
1caa12d0
TG
680 uint8_t msb_octet = *(uint8_t*) addr;
681
682 /* addr may not be aligned, so make sure we only access it byte-wise */
df40eee8
TG
683
684 assert(addr);
df40eee8
TG
685 assert(prefixlen);
686
1caa12d0 687 if (msb_octet < 128)
df40eee8
TG
688 /* class A, leading bits: 0 */
689 *prefixlen = 8;
1caa12d0 690 else if (msb_octet < 192)
df40eee8
TG
691 /* class B, leading bits 10 */
692 *prefixlen = 16;
1caa12d0 693 else if (msb_octet < 224)
df40eee8
TG
694 /* class C, leading bits 110 */
695 *prefixlen = 24;
696 else
697 /* class D or E, no default prefixlen */
698 return -ERANGE;
699
700 return 0;
701}
702
5a941f5f 703int in4_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mask) {
df40eee8
TG
704 unsigned char prefixlen;
705 int r;
706
707 assert(addr);
708 assert(mask);
709
5a941f5f 710 r = in4_addr_default_prefixlen(addr, &prefixlen);
df40eee8
TG
711 if (r < 0)
712 return r;
713
5a941f5f 714 in4_addr_prefixlen_to_netmask(mask, prefixlen);
df40eee8
TG
715 return 0;
716}
5a8bcb67 717
333f7d89
YW
718int in4_addr_mask(struct in_addr *addr, unsigned char prefixlen) {
719 struct in_addr mask;
5a8bcb67 720
333f7d89 721 assert(addr);
5a8bcb67 722
333f7d89
YW
723 if (!in4_addr_prefixlen_to_netmask(&mask, prefixlen))
724 return -EINVAL;
5a8bcb67 725
333f7d89
YW
726 addr->s_addr &= mask.s_addr;
727 return 0;
728}
5a8bcb67 729
333f7d89
YW
730int in6_addr_mask(struct in6_addr *addr, unsigned char prefixlen) {
731 unsigned i;
5a8bcb67 732
333f7d89
YW
733 for (i = 0; i < 16; i++) {
734 uint8_t mask;
5a8bcb67 735
333f7d89
YW
736 if (prefixlen >= 8) {
737 mask = 0xFF;
738 prefixlen -= 8;
6df860f3 739 } else if (prefixlen > 0) {
333f7d89
YW
740 mask = 0xFF << (8 - prefixlen);
741 prefixlen = 0;
6df860f3
YW
742 } else {
743 assert(prefixlen == 0);
744 mask = 0;
5a8bcb67
LP
745 }
746
333f7d89 747 addr->s6_addr[i] &= mask;
5a8bcb67
LP
748 }
749
333f7d89
YW
750 return 0;
751}
752
753int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen) {
754 assert(addr);
755
756 switch (family) {
757 case AF_INET:
758 return in4_addr_mask(&addr->in, prefixlen);
759 case AF_INET6:
760 return in6_addr_mask(&addr->in6, prefixlen);
761 default:
762 return -EAFNOSUPPORT;
763 }
5a8bcb67 764}
f7bf1abe 765
45e76094 766int in4_addr_prefix_covers_full(
e174b43f
YW
767 const struct in_addr *prefix,
768 unsigned char prefixlen,
45e76094
YW
769 const struct in_addr *address,
770 unsigned char address_prefixlen) {
1274b6c6 771
e174b43f 772 struct in_addr masked_prefix, masked_address;
1274b6c6
LP
773 int r;
774
775 assert(prefix);
776 assert(address);
777
45e76094
YW
778 if (prefixlen > address_prefixlen)
779 return false;
780
1274b6c6 781 masked_prefix = *prefix;
e174b43f 782 r = in4_addr_mask(&masked_prefix, prefixlen);
1274b6c6
LP
783 if (r < 0)
784 return r;
785
786 masked_address = *address;
e174b43f 787 r = in4_addr_mask(&masked_address, prefixlen);
1274b6c6
LP
788 if (r < 0)
789 return r;
790
e174b43f
YW
791 return in4_addr_equal(&masked_prefix, &masked_address);
792}
793
45e76094 794int in6_addr_prefix_covers_full(
e174b43f
YW
795 const struct in6_addr *prefix,
796 unsigned char prefixlen,
45e76094
YW
797 const struct in6_addr *address,
798 unsigned char address_prefixlen) {
e174b43f
YW
799
800 struct in6_addr masked_prefix, masked_address;
801 int r;
802
803 assert(prefix);
804 assert(address);
805
45e76094
YW
806 if (prefixlen > address_prefixlen)
807 return false;
808
e174b43f
YW
809 masked_prefix = *prefix;
810 r = in6_addr_mask(&masked_prefix, prefixlen);
811 if (r < 0)
812 return r;
813
814 masked_address = *address;
815 r = in6_addr_mask(&masked_address, prefixlen);
816 if (r < 0)
817 return r;
818
819 return in6_addr_equal(&masked_prefix, &masked_address);
820}
821
45e76094 822int in_addr_prefix_covers_full(
e174b43f
YW
823 int family,
824 const union in_addr_union *prefix,
825 unsigned char prefixlen,
45e76094
YW
826 const union in_addr_union *address,
827 unsigned char address_prefixlen) {
e174b43f
YW
828
829 assert(prefix);
830 assert(address);
831
832 switch (family) {
833 case AF_INET:
45e76094 834 return in4_addr_prefix_covers_full(&prefix->in, prefixlen, &address->in, address_prefixlen);
e174b43f 835 case AF_INET6:
45e76094 836 return in6_addr_prefix_covers_full(&prefix->in6, prefixlen, &address->in6, address_prefixlen);
e174b43f
YW
837 default:
838 return -EAFNOSUPPORT;
839 }
1274b6c6
LP
840}
841
f4912f3a
LP
842int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret) {
843 uint8_t u;
844 int r;
845
846 if (!IN_SET(family, AF_INET, AF_INET6))
847 return -EAFNOSUPPORT;
848
849 r = safe_atou8(p, &u);
850 if (r < 0)
851 return r;
852
853 if (u > FAMILY_ADDRESS_SIZE(family) * 8)
854 return -ERANGE;
855
856 *ret = u;
857 return 0;
858}
859
9e0fdc21 860int in_addr_prefix_from_string(
f4912f3a
LP
861 const char *p,
862 int family,
863 union in_addr_union *ret_prefix,
864 unsigned char *ret_prefixlen) {
865
67944f5c 866 _cleanup_free_ char *str = NULL;
f7bf1abe
SS
867 union in_addr_union buffer;
868 const char *e, *l;
f4912f3a 869 unsigned char k;
f7bf1abe
SS
870 int r;
871
872 assert(p);
873
874 if (!IN_SET(family, AF_INET, AF_INET6))
875 return -EAFNOSUPPORT;
876
877 e = strchr(p, '/');
67944f5c
YW
878 if (e) {
879 str = strndup(p, e - p);
880 if (!str)
881 return -ENOMEM;
882
883 l = str;
884 } else
f7bf1abe
SS
885 l = p;
886
887 r = in_addr_from_string(family, l, &buffer);
888 if (r < 0)
889 return r;
890
f7bf1abe 891 if (e) {
f4912f3a 892 r = in_addr_parse_prefixlen(family, e+1, &k);
f7bf1abe
SS
893 if (r < 0)
894 return r;
f4912f3a
LP
895 } else
896 k = FAMILY_ADDRESS_SIZE(family) * 8;
f7bf1abe 897
f4912f3a
LP
898 if (ret_prefix)
899 *ret_prefix = buffer;
900 if (ret_prefixlen)
901 *ret_prefixlen = k;
f7bf1abe 902
f4912f3a
LP
903 return 0;
904}
f7bf1abe 905
c1316cd0 906int in_addr_prefix_from_string_auto_full(
f4912f3a 907 const char *p,
9e0fdc21 908 InAddrPrefixLenMode mode,
f4912f3a
LP
909 int *ret_family,
910 union in_addr_union *ret_prefix,
911 unsigned char *ret_prefixlen) {
912
67944f5c 913 _cleanup_free_ char *str = NULL;
f4912f3a
LP
914 union in_addr_union buffer;
915 const char *e, *l;
916 unsigned char k;
917 int family, r;
918
919 assert(p);
920
921 e = strchr(p, '/');
67944f5c
YW
922 if (e) {
923 str = strndup(p, e - p);
924 if (!str)
925 return -ENOMEM;
926
927 l = str;
928 } else
f4912f3a
LP
929 l = p;
930
931 r = in_addr_from_string_auto(l, &family, &buffer);
932 if (r < 0)
933 return r;
934
935 if (e) {
936 r = in_addr_parse_prefixlen(family, e+1, &k);
937 if (r < 0)
a4798d4e 938 return r;
f4912f3a 939 } else
9e0fdc21
YW
940 switch (mode) {
941 case PREFIXLEN_FULL:
942 k = FAMILY_ADDRESS_SIZE(family) * 8;
943 break;
944 case PREFIXLEN_REFUSE:
945 return -ENOANO; /* To distinguish this error from others. */
9e0fdc21 946 default:
04499a70 947 assert_not_reached();
9e0fdc21 948 }
f4912f3a
LP
949
950 if (ret_family)
951 *ret_family = family;
952 if (ret_prefix)
953 *ret_prefix = buffer;
954 if (ret_prefixlen)
955 *ret_prefixlen = k;
f7bf1abe
SS
956
957 return 0;
958}
6c39e026 959
c01a5c05
YW
960void in_addr_hash_func(const union in_addr_union *u, int family, struct siphash *state) {
961 assert(u);
962 assert(state);
963
964 siphash24_compress(u->bytes, FAMILY_ADDRESS_SIZE(family), state);
965}
966
4596c836 967void in_addr_data_hash_func(const struct in_addr_data *a, struct siphash *state) {
93e44aa9
YW
968 assert(a);
969 assert(state);
970
c01a5c05
YW
971 siphash24_compress_typesafe(a->family, state);
972 in_addr_hash_func(&a->address, a->family, state);
6c39e026
YW
973}
974
4596c836 975int in_addr_data_compare_func(const struct in_addr_data *x, const struct in_addr_data *y) {
a0edd02e 976 int r;
6c39e026 977
93e44aa9
YW
978 assert(x);
979 assert(y);
980
a0edd02e
FB
981 r = CMP(x->family, y->family);
982 if (r != 0)
983 return r;
6c39e026 984
23577246 985 return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
6c39e026
YW
986}
987
4596c836
YW
988DEFINE_HASH_OPS(
989 in_addr_data_hash_ops,
990 struct in_addr_data,
991 in_addr_data_hash_func,
992 in_addr_data_compare_func);
993
994DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
995 in_addr_data_hash_ops_free,
996 struct in_addr_data,
997 in_addr_data_hash_func,
998 in_addr_data_compare_func,
999 free);
2968913e 1000
badd4928 1001void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) {
2968913e 1002 assert(addr);
93e44aa9 1003 assert(state);
2968913e 1004
c01a5c05 1005 siphash24_compress_typesafe(*addr, state);
2968913e
YW
1006}
1007
badd4928 1008int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) {
93e44aa9
YW
1009 assert(a);
1010 assert(b);
1011
2968913e
YW
1012 return memcmp(a, b, sizeof(*a));
1013}
1014
4596c836
YW
1015DEFINE_HASH_OPS(
1016 in6_addr_hash_ops,
1017 struct in6_addr,
1018 in6_addr_hash_func,
1019 in6_addr_compare_func);
1020
f1cb8933
YW
1021DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
1022 in6_addr_hash_ops_free,
1023 struct in6_addr,
1024 in6_addr_hash_func,
1025 in6_addr_compare_func,
1026 free);