]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/basic/in-addr-util.c
basic/include: replace _Static_assert() with static_assert()
[thirdparty/systemd.git] / src / basic / in-addr-util.c
... / ...
CommitLineData
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3#include <arpa/inet.h>
4#include <endian.h>
5#include <stdio.h>
6
7#include "alloc-util.h"
8#include "errno-util.h"
9#include "hash-funcs.h"
10#include "in-addr-util.h"
11#include "logarithm.h"
12#include "memory-util.h"
13#include "parse-util.h"
14#include "random-util.h"
15#include "siphash24.h"
16#include "stdio-util.h"
17#include "string-util.h"
18
19bool in4_addr_is_null(const struct in_addr *a) {
20 assert(a);
21
22 return a->s_addr == 0;
23}
24
25bool in6_addr_is_null(const struct in6_addr *a) {
26 assert(a);
27
28 return eqzero(a->s6_addr32);
29}
30
31int in_addr_is_null(int family, const union in_addr_union *u) {
32 assert(u);
33
34 if (family == AF_INET)
35 return in4_addr_is_null(&u->in);
36
37 if (family == AF_INET6)
38 return in6_addr_is_null(&u->in6);
39
40 return -EAFNOSUPPORT;
41}
42
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
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
63bool in6_addr_is_link_local(const struct in6_addr *a) {
64 assert(a);
65
66 return (a->s6_addr32[0] & htobe32(0xffc00000)) == htobe32(0xfe800000);
67}
68
69int in_addr_is_link_local(int family, const union in_addr_union *u) {
70 assert(u);
71
72 if (family == AF_INET)
73 return in4_addr_is_link_local(&u->in);
74
75 if (family == AF_INET6)
76 return in6_addr_is_link_local(&u->in6);
77
78 return -EAFNOSUPPORT;
79}
80
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
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
100 return a->s6_addr[0] == 0xff;
101}
102
103int in_addr_is_multicast(int family, const union in_addr_union *u) {
104 assert(u);
105
106 if (family == AF_INET)
107 return in4_addr_is_multicast(&u->in);
108
109 if (family == AF_INET6)
110 return in6_addr_is_multicast(&u->in6);
111
112 return -EAFNOSUPPORT;
113}
114
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
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
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
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
140int in_addr_is_localhost(int family, const union in_addr_union *u) {
141 assert(u);
142
143 if (family == AF_INET)
144 return in4_addr_is_localhost(&u->in);
145
146 if (family == AF_INET6)
147 return in6_addr_is_loopback(&u->in6);
148
149 return -EAFNOSUPPORT;
150}
151
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)
160 return in6_addr_is_loopback(&u->in6);
161
162 return -EAFNOSUPPORT;
163}
164
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
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
178bool in6_addr_equal(const struct in6_addr *a, const struct in6_addr *b) {
179 assert(a);
180 assert(b);
181
182 return memcmp(a, b, sizeof(struct in6_addr)) == 0;
183}
184
185int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b) {
186 assert(a);
187 assert(b);
188
189 if (family == AF_INET)
190 return in4_addr_equal(&a->in, &b->in);
191
192 if (family == AF_INET6)
193 return in6_addr_equal(&a->in6, &b->in6);
194
195 return -EAFNOSUPPORT;
196}
197
198bool in4_addr_prefix_intersect(
199 const struct in_addr *a,
200 unsigned aprefixlen,
201 const struct in_addr *b,
202 unsigned bprefixlen) {
203
204 assert(a);
205 assert(b);
206
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. */
210
211 uint32_t x = be32toh(a->s_addr ^ b->s_addr);
212 uint32_t n = 0xFFFFFFFFUL << (32 - m);
213 return (x & n) == 0;
214}
215
216bool in6_addr_prefix_intersect(
217 const struct in6_addr *a,
218 unsigned aprefixlen,
219 const struct in6_addr *b,
220 unsigned bprefixlen) {
221
222 assert(a);
223 assert(b);
224
225 unsigned m = MIN3(aprefixlen, bprefixlen, (unsigned) (sizeof(struct in6_addr) * 8));
226 if (m == 0)
227 return true;
228
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;
234
235 if (m <= 8)
236 break;
237
238 m -= 8;
239 }
240
241 return true;
242}
243
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) {
250
251 assert(a);
252 assert(b);
253
254 /* Checks whether there are any addresses that are in both networks. */
255
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);
261
262 return -EAFNOSUPPORT;
263}
264
265int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen) {
266 assert(u);
267
268 /* Increases the network part of an address by one. Returns 0 if that succeeds, or -ERANGE if
269 * this overflows. */
270
271 return in_addr_prefix_nth(family, u, prefixlen, 1);
272}
273
274/*
275 * Calculates the nth prefix of size prefixlen starting from the address denoted by u.
276 *
277 * On success 0 will be returned and the calculated prefix will be available in
278 * u. In case the calculation cannot be performed (invalid prefix length,
279 * overflows would occur) -ERANGE is returned. If the address family given isn't
280 * supported -EAFNOSUPPORT will be returned.
281 *
282 * Examples:
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
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
287 * - in_addr_prefix_nth(AF_INET6, 2001:db8, 64, 0xff00) returns 0, writes 2001:0db8:0000:ff00:: to u
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
295 if (family == AF_INET) {
296 uint32_t c, n, t;
297
298 if (prefixlen > 32)
299 return -ERANGE;
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);
313 return 0;
314 }
315
316 if (family == AF_INET6) {
317 bool overflow = false;
318
319 if (prefixlen > 128)
320 return -ERANGE;
321
322 for (unsigned i = 16; i > 0; i--) {
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);
341 }
342
343 if (overflow || nth != 0)
344 return -ERANGE;
345
346 return 0;
347 }
348
349 return -EAFNOSUPPORT;
350}
351
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 }
425
426 return -EAFNOSUPPORT;
427}
428
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
466int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
467 _cleanup_free_ char *x = NULL;
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;
485 if (!typesafe_inet_ntop(family, u, x, l))
486 return errno_or_else(EINVAL);
487
488 *ret = TAKE_PTR(x);
489 return 0;
490}
491
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
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) {
510
511 assert(u);
512 assert(buf);
513
514 if (!IN_SET(family, AF_INET, AF_INET6))
515 return -EAFNOSUPPORT;
516
517 errno = 0;
518 if (!typesafe_inet_ntop(family, u, buf, buf_len))
519 return errno_or_else(ENOSPC);
520
521 size_t l = strlen(buf);
522 if (!snprintf_ok(buf + l, buf_len - l, "/%u", prefixlen))
523 return -ENOSPC;
524 return 0;
525}
526
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
582int in_addr_from_string(int family, const char *s, union in_addr_union *ret) {
583 union in_addr_union buffer;
584 assert(s);
585
586 if (!IN_SET(family, AF_INET, AF_INET6))
587 return -EAFNOSUPPORT;
588
589 errno = 0;
590 if (inet_pton(family, s, ret ?: &buffer) <= 0)
591 return errno_or_else(EINVAL);
592
593 return 0;
594}
595
596int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret) {
597 int r;
598
599 assert(s);
600
601 r = in_addr_from_string(AF_INET, s, ret);
602 if (r >= 0) {
603 if (ret_family)
604 *ret_family = AF_INET;
605 return 0;
606 }
607
608 r = in_addr_from_string(AF_INET6, s, ret);
609 if (r >= 0) {
610 if (ret_family)
611 *ret_family = AF_INET6;
612 return 0;
613 }
614
615 return -EINVAL;
616}
617
618unsigned char in4_addr_netmask_to_prefixlen(const struct in_addr *addr) {
619 assert(addr);
620
621 return 32U - u32ctz(be32toh(addr->s_addr));
622}
623
624/* Calculate an IPv4 netmask from prefix length, for example /8 -> 255.0.0.0. */
625struct in_addr* in4_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char prefixlen) {
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
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
679int in4_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen) {
680 uint8_t msb_octet = *(uint8_t*) addr;
681
682 /* addr may not be aligned, so make sure we only access it byte-wise */
683
684 assert(addr);
685 assert(prefixlen);
686
687 if (msb_octet < 128)
688 /* class A, leading bits: 0 */
689 *prefixlen = 8;
690 else if (msb_octet < 192)
691 /* class B, leading bits 10 */
692 *prefixlen = 16;
693 else if (msb_octet < 224)
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
703int in4_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mask) {
704 unsigned char prefixlen;
705 int r;
706
707 assert(addr);
708 assert(mask);
709
710 r = in4_addr_default_prefixlen(addr, &prefixlen);
711 if (r < 0)
712 return r;
713
714 in4_addr_prefixlen_to_netmask(mask, prefixlen);
715 return 0;
716}
717
718int in4_addr_mask(struct in_addr *addr, unsigned char prefixlen) {
719 struct in_addr mask;
720
721 assert(addr);
722
723 if (!in4_addr_prefixlen_to_netmask(&mask, prefixlen))
724 return -EINVAL;
725
726 addr->s_addr &= mask.s_addr;
727 return 0;
728}
729
730int in6_addr_mask(struct in6_addr *addr, unsigned char prefixlen) {
731 unsigned i;
732
733 for (i = 0; i < 16; i++) {
734 uint8_t mask;
735
736 if (prefixlen >= 8) {
737 mask = 0xFF;
738 prefixlen -= 8;
739 } else if (prefixlen > 0) {
740 mask = 0xFF << (8 - prefixlen);
741 prefixlen = 0;
742 } else {
743 assert(prefixlen == 0);
744 mask = 0;
745 }
746
747 addr->s6_addr[i] &= mask;
748 }
749
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 }
764}
765
766int in4_addr_prefix_covers_full(
767 const struct in_addr *prefix,
768 unsigned char prefixlen,
769 const struct in_addr *address,
770 unsigned char address_prefixlen) {
771
772 struct in_addr masked_prefix, masked_address;
773 int r;
774
775 assert(prefix);
776 assert(address);
777
778 if (prefixlen > address_prefixlen)
779 return false;
780
781 masked_prefix = *prefix;
782 r = in4_addr_mask(&masked_prefix, prefixlen);
783 if (r < 0)
784 return r;
785
786 masked_address = *address;
787 r = in4_addr_mask(&masked_address, prefixlen);
788 if (r < 0)
789 return r;
790
791 return in4_addr_equal(&masked_prefix, &masked_address);
792}
793
794int in6_addr_prefix_covers_full(
795 const struct in6_addr *prefix,
796 unsigned char prefixlen,
797 const struct in6_addr *address,
798 unsigned char address_prefixlen) {
799
800 struct in6_addr masked_prefix, masked_address;
801 int r;
802
803 assert(prefix);
804 assert(address);
805
806 if (prefixlen > address_prefixlen)
807 return false;
808
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
822int in_addr_prefix_covers_full(
823 int family,
824 const union in_addr_union *prefix,
825 unsigned char prefixlen,
826 const union in_addr_union *address,
827 unsigned char address_prefixlen) {
828
829 assert(prefix);
830 assert(address);
831
832 switch (family) {
833 case AF_INET:
834 return in4_addr_prefix_covers_full(&prefix->in, prefixlen, &address->in, address_prefixlen);
835 case AF_INET6:
836 return in6_addr_prefix_covers_full(&prefix->in6, prefixlen, &address->in6, address_prefixlen);
837 default:
838 return -EAFNOSUPPORT;
839 }
840}
841
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
860int in_addr_prefix_from_string(
861 const char *p,
862 int family,
863 union in_addr_union *ret_prefix,
864 unsigned char *ret_prefixlen) {
865
866 _cleanup_free_ char *str = NULL;
867 union in_addr_union buffer;
868 const char *e, *l;
869 unsigned char k;
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, '/');
878 if (e) {
879 str = strndup(p, e - p);
880 if (!str)
881 return -ENOMEM;
882
883 l = str;
884 } else
885 l = p;
886
887 r = in_addr_from_string(family, l, &buffer);
888 if (r < 0)
889 return r;
890
891 if (e) {
892 r = in_addr_parse_prefixlen(family, e+1, &k);
893 if (r < 0)
894 return r;
895 } else
896 k = FAMILY_ADDRESS_SIZE(family) * 8;
897
898 if (ret_prefix)
899 *ret_prefix = buffer;
900 if (ret_prefixlen)
901 *ret_prefixlen = k;
902
903 return 0;
904}
905
906int in_addr_prefix_from_string_auto_full(
907 const char *p,
908 InAddrPrefixLenMode mode,
909 int *ret_family,
910 union in_addr_union *ret_prefix,
911 unsigned char *ret_prefixlen) {
912
913 _cleanup_free_ char *str = NULL;
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, '/');
922 if (e) {
923 str = strndup(p, e - p);
924 if (!str)
925 return -ENOMEM;
926
927 l = str;
928 } else
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)
938 return r;
939 } else
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. */
946 default:
947 assert_not_reached();
948 }
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;
956
957 return 0;
958}
959
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
967void in_addr_data_hash_func(const struct in_addr_data *a, struct siphash *state) {
968 assert(a);
969 assert(state);
970
971 siphash24_compress_typesafe(a->family, state);
972 in_addr_hash_func(&a->address, a->family, state);
973}
974
975int in_addr_data_compare_func(const struct in_addr_data *x, const struct in_addr_data *y) {
976 int r;
977
978 assert(x);
979 assert(y);
980
981 r = CMP(x->family, y->family);
982 if (r != 0)
983 return r;
984
985 return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
986}
987
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);
1000
1001void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) {
1002 assert(addr);
1003 assert(state);
1004
1005 siphash24_compress_typesafe(*addr, state);
1006}
1007
1008int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) {
1009 assert(a);
1010 assert(b);
1011
1012 return memcmp(a, b, sizeof(*a));
1013}
1014
1015DEFINE_HASH_OPS(
1016 in6_addr_hash_ops,
1017 struct in6_addr,
1018 in6_addr_hash_func,
1019 in6_addr_compare_func);
1020
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);