]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/in-addr-util.c
in-addr-util: introduce in6_addr_is_link_local_all_nodes()
[thirdparty/systemd.git] / src / basic / in-addr-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <arpa/inet.h>
4 #include <endian.h>
5 #include <errno.h>
6 #include <net/if.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10
11 #include "alloc-util.h"
12 #include "errno-util.h"
13 #include "in-addr-util.h"
14 #include "macro.h"
15 #include "parse-util.h"
16 #include "random-util.h"
17 #include "string-util.h"
18 #include "strxcpyx.h"
19 #include "util.h"
20
21 bool in4_addr_is_null(const struct in_addr *a) {
22 assert(a);
23
24 return a->s_addr == 0;
25 }
26
27 int in_addr_is_null(int family, const union in_addr_union *u) {
28 assert(u);
29
30 if (family == AF_INET)
31 return in4_addr_is_null(&u->in);
32
33 if (family == AF_INET6)
34 return IN6_IS_ADDR_UNSPECIFIED(&u->in6);
35
36 return -EAFNOSUPPORT;
37 }
38
39 bool in4_addr_is_link_local(const struct in_addr *a) {
40 assert(a);
41
42 return (be32toh(a->s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
43 }
44
45 int in_addr_is_link_local(int family, const union in_addr_union *u) {
46 assert(u);
47
48 if (family == AF_INET)
49 return in4_addr_is_link_local(&u->in);
50
51 if (family == AF_INET6)
52 return IN6_IS_ADDR_LINKLOCAL(&u->in6);
53
54 return -EAFNOSUPPORT;
55 }
56
57 bool in6_addr_is_link_local_all_nodes(const struct in6_addr *a) {
58 assert(a);
59
60 /* ff02::1 */
61 return be32toh(a->s6_addr32[0]) == UINT32_C(0xff020000) &&
62 a->s6_addr32[1] == 0 &&
63 a->s6_addr32[2] == 0 &&
64 be32toh(a->s6_addr32[3]) == UINT32_C(0x00000001);
65 }
66
67 int in_addr_is_multicast(int family, const union in_addr_union *u) {
68 assert(u);
69
70 if (family == AF_INET)
71 return IN_MULTICAST(be32toh(u->in.s_addr));
72
73 if (family == AF_INET6)
74 return IN6_IS_ADDR_MULTICAST(&u->in6);
75
76 return -EAFNOSUPPORT;
77 }
78
79 bool in4_addr_is_localhost(const struct in_addr *a) {
80 assert(a);
81
82 /* All of 127.x.x.x is localhost. */
83 return (be32toh(a->s_addr) & UINT32_C(0xFF000000)) == UINT32_C(127) << 24;
84 }
85
86 bool in4_addr_is_non_local(const struct in_addr *a) {
87 /* Whether the address is not null and not localhost.
88 *
89 * As such, it is suitable to configure as DNS/NTP server from DHCP. */
90 return !in4_addr_is_null(a) &&
91 !in4_addr_is_localhost(a);
92 }
93
94 int in_addr_is_localhost(int family, const union in_addr_union *u) {
95 assert(u);
96
97 if (family == AF_INET)
98 return in4_addr_is_localhost(&u->in);
99
100 if (family == AF_INET6)
101 return IN6_IS_ADDR_LOOPBACK(&u->in6);
102
103 return -EAFNOSUPPORT;
104 }
105
106 bool in4_addr_equal(const struct in_addr *a, const struct in_addr *b) {
107 assert(a);
108 assert(b);
109
110 return a->s_addr == b->s_addr;
111 }
112
113 int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b) {
114 assert(a);
115 assert(b);
116
117 if (family == AF_INET)
118 return in4_addr_equal(&a->in, &b->in);
119
120 if (family == AF_INET6)
121 return IN6_ARE_ADDR_EQUAL(&a->in6, &b->in6);
122
123 return -EAFNOSUPPORT;
124 }
125
126 int in_addr_prefix_intersect(
127 int family,
128 const union in_addr_union *a,
129 unsigned aprefixlen,
130 const union in_addr_union *b,
131 unsigned bprefixlen) {
132
133 unsigned m;
134
135 assert(a);
136 assert(b);
137
138 /* Checks whether there are any addresses that are in both
139 * networks */
140
141 m = MIN(aprefixlen, bprefixlen);
142
143 if (family == AF_INET) {
144 uint32_t x, nm;
145
146 x = be32toh(a->in.s_addr ^ b->in.s_addr);
147 nm = (m == 0) ? 0 : 0xFFFFFFFFUL << (32 - m);
148
149 return (x & nm) == 0;
150 }
151
152 if (family == AF_INET6) {
153 unsigned i;
154
155 if (m > 128)
156 m = 128;
157
158 for (i = 0; i < 16; i++) {
159 uint8_t x, nm;
160
161 x = a->in6.s6_addr[i] ^ b->in6.s6_addr[i];
162
163 if (m < 8)
164 nm = 0xFF << (8 - m);
165 else
166 nm = 0xFF;
167
168 if ((x & nm) != 0)
169 return 0;
170
171 if (m > 8)
172 m -= 8;
173 else
174 m = 0;
175 }
176
177 return 1;
178 }
179
180 return -EAFNOSUPPORT;
181 }
182
183 int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen) {
184 assert(u);
185
186 /* Increases the network part of an address by one. Returns
187 * positive if that succeeds, or -ERANGE if this overflows. */
188
189 return in_addr_prefix_nth(family, u, prefixlen, 1);
190 }
191
192 /*
193 * Calculates the nth prefix of size prefixlen starting from the address denoted by u.
194 *
195 * On success 1 will be returned and the calculated prefix will be available in
196 * u. In the case nth == 0 the input will be left unchanged and 1 will be returned.
197 * In case the calculation cannot be performed (invalid prefix length,
198 * overflows would occur) -ERANGE is returned. If the address family given isn't
199 * supported -EAFNOSUPPORT will be returned.
200 *
201 *
202 * Examples:
203 * - in_addr_prefix_nth(AF_INET, 192.168.0.0, 24, 2), returns 1, writes 192.168.2.0 to u
204 * - in_addr_prefix_nth(AF_INET, 192.168.0.0, 24, 0), returns 1, no data written
205 * - in_addr_prefix_nth(AF_INET, 255.255.255.0, 24, 1), returns -ERANGE, no data written
206 * - in_addr_prefix_nth(AF_INET, 255.255.255.0, 0, 1), returns -ERANGE, no data written
207 * - in_addr_prefix_nth(AF_INET6, 2001:db8, 64, 0xff00) returns 1, writes 2001:0db8:0000:ff00:: to u
208 */
209 int in_addr_prefix_nth(int family, union in_addr_union *u, unsigned prefixlen, uint64_t nth) {
210 assert(u);
211
212 if (prefixlen <= 0)
213 return -ERANGE;
214
215 if (nth == 0)
216 return 1;
217
218 if (family == AF_INET) {
219 uint32_t c, n, t;
220 if (prefixlen > 32)
221 prefixlen = 32;
222
223 c = be32toh(u->in.s_addr);
224
225 t = nth << (32 - prefixlen);
226
227 /* Check for wrap */
228 if (c > UINT32_MAX - t)
229 return -ERANGE;
230
231 n = c + t;
232
233 n &= UINT32_C(0xFFFFFFFF) << (32 - prefixlen);
234 u->in.s_addr = htobe32(n);
235 return 1;
236 }
237
238 if (family == AF_INET6) {
239 struct in6_addr result = {};
240 uint8_t overflow = 0;
241 uint64_t delta; /* this assumes that we only ever have to up to 1<<64 subnets */
242 unsigned start_byte = (prefixlen - 1) / 8;
243
244 if (prefixlen > 128)
245 prefixlen = 128;
246
247 /* First calculate what we have to add */
248 delta = nth << ((128 - prefixlen) % 8);
249
250 for (unsigned i = 16; i > 0; i--) {
251 unsigned j = i - 1;
252 unsigned d = 0;
253
254 if (j <= start_byte) {
255 int16_t t;
256
257 d = delta & 0xFF;
258 delta >>= 8;
259
260 t = u->in6.s6_addr[j] + d + overflow;
261 overflow = t > UINT8_MAX ? t - UINT8_MAX : 0;
262
263 result.s6_addr[j] = (uint8_t)t;
264 } else
265 result.s6_addr[j] = u->in6.s6_addr[j];
266 }
267
268 if (overflow || delta != 0)
269 return -ERANGE;
270
271 u->in6 = result;
272 return 1;
273 }
274
275 return -EAFNOSUPPORT;
276 }
277
278 int in_addr_random_prefix(
279 int family,
280 union in_addr_union *u,
281 unsigned prefixlen_fixed_part,
282 unsigned prefixlen) {
283
284 assert(u);
285
286 /* Random network part of an address by one. */
287
288 if (prefixlen <= 0)
289 return 0;
290
291 if (family == AF_INET) {
292 uint32_t c, n;
293
294 if (prefixlen_fixed_part > 32)
295 prefixlen_fixed_part = 32;
296 if (prefixlen > 32)
297 prefixlen = 32;
298 if (prefixlen_fixed_part >= prefixlen)
299 return -EINVAL;
300
301 c = be32toh(u->in.s_addr);
302 c &= ((UINT32_C(1) << prefixlen_fixed_part) - 1) << (32 - prefixlen_fixed_part);
303
304 random_bytes(&n, sizeof(n));
305 n &= ((UINT32_C(1) << (prefixlen - prefixlen_fixed_part)) - 1) << (32 - prefixlen);
306
307 u->in.s_addr = htobe32(n | c);
308 return 1;
309 }
310
311 if (family == AF_INET6) {
312 struct in6_addr n;
313 unsigned i, j;
314
315 if (prefixlen_fixed_part > 128)
316 prefixlen_fixed_part = 128;
317 if (prefixlen > 128)
318 prefixlen = 128;
319 if (prefixlen_fixed_part >= prefixlen)
320 return -EINVAL;
321
322 random_bytes(&n, sizeof(n));
323
324 for (i = 0; i < 16; i++) {
325 uint8_t mask_fixed_part = 0, mask = 0;
326
327 if (i < (prefixlen_fixed_part + 7) / 8) {
328 if (i < prefixlen_fixed_part / 8)
329 mask_fixed_part = 0xffu;
330 else {
331 j = prefixlen_fixed_part % 8;
332 mask_fixed_part = ((UINT8_C(1) << (j + 1)) - 1) << (8 - j);
333 }
334 }
335
336 if (i < (prefixlen + 7) / 8) {
337 if (i < prefixlen / 8)
338 mask = 0xffu ^ mask_fixed_part;
339 else {
340 j = prefixlen % 8;
341 mask = (((UINT8_C(1) << (j + 1)) - 1) << (8 - j)) ^ mask_fixed_part;
342 }
343 }
344
345 u->in6.s6_addr[i] &= mask_fixed_part;
346 u->in6.s6_addr[i] |= n.s6_addr[i] & mask;
347 }
348
349 return 1;
350 }
351
352 return -EAFNOSUPPORT;
353 }
354
355 int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
356 _cleanup_free_ char *x = NULL;
357 size_t l;
358
359 assert(u);
360 assert(ret);
361
362 if (family == AF_INET)
363 l = INET_ADDRSTRLEN;
364 else if (family == AF_INET6)
365 l = INET6_ADDRSTRLEN;
366 else
367 return -EAFNOSUPPORT;
368
369 x = new(char, l);
370 if (!x)
371 return -ENOMEM;
372
373 errno = 0;
374 if (!inet_ntop(family, u, x, l))
375 return errno_or_else(EINVAL);
376
377 *ret = TAKE_PTR(x);
378 return 0;
379 }
380
381 int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret) {
382 _cleanup_free_ char *x = NULL;
383 char *p;
384 size_t l;
385
386 assert(u);
387 assert(ret);
388
389 if (family == AF_INET)
390 l = INET_ADDRSTRLEN + 3;
391 else if (family == AF_INET6)
392 l = INET6_ADDRSTRLEN + 4;
393 else
394 return -EAFNOSUPPORT;
395
396 if (prefixlen > FAMILY_ADDRESS_SIZE(family) * 8)
397 return -EINVAL;
398
399 x = new(char, l);
400 if (!x)
401 return -ENOMEM;
402
403 errno = 0;
404 if (!inet_ntop(family, u, x, l))
405 return errno_or_else(EINVAL);
406
407 p = x + strlen(x);
408 l -= strlen(x);
409 (void) strpcpyf(&p, l, "/%u", prefixlen);
410
411 *ret = TAKE_PTR(x);
412 return 0;
413 }
414
415 int 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) {
416 _cleanup_free_ char *ip_str = NULL, *x = NULL;
417 int r;
418
419 assert(IN_SET(family, AF_INET, AF_INET6));
420 assert(u);
421 assert(ret);
422
423 /* Much like in_addr_to_string(), but optionally appends the zone interface index to the address, to properly
424 * handle IPv6 link-local addresses. */
425
426 r = in_addr_to_string(family, u, &ip_str);
427 if (r < 0)
428 return r;
429
430 if (family == AF_INET6) {
431 r = in_addr_is_link_local(family, u);
432 if (r < 0)
433 return r;
434 if (r == 0)
435 ifindex = 0;
436 } else
437 ifindex = 0; /* For IPv4 address, ifindex is always ignored. */
438
439 if (port == 0 && ifindex == 0 && isempty(server_name)) {
440 *ret = TAKE_PTR(ip_str);
441 return 0;
442 }
443
444 const char *separator = isempty(server_name) ? "" : "#";
445 server_name = strempty(server_name);
446
447 if (port > 0) {
448 if (family == AF_INET6) {
449 if (ifindex > 0)
450 r = asprintf(&x, "[%s]:%"PRIu16"%%%i%s%s", ip_str, port, ifindex, separator, server_name);
451 else
452 r = asprintf(&x, "[%s]:%"PRIu16"%s%s", ip_str, port, separator, server_name);
453 } else
454 r = asprintf(&x, "%s:%"PRIu16"%s%s", ip_str, port, separator, server_name);
455 } else {
456 if (ifindex > 0)
457 r = asprintf(&x, "%s%%%i%s%s", ip_str, ifindex, separator, server_name);
458 else {
459 x = strjoin(ip_str, separator, server_name);
460 r = x ? 0 : -ENOMEM;
461 }
462 }
463 if (r < 0)
464 return -ENOMEM;
465
466 *ret = TAKE_PTR(x);
467 return 0;
468 }
469
470 int in_addr_from_string(int family, const char *s, union in_addr_union *ret) {
471 union in_addr_union buffer;
472 assert(s);
473
474 if (!IN_SET(family, AF_INET, AF_INET6))
475 return -EAFNOSUPPORT;
476
477 errno = 0;
478 if (inet_pton(family, s, ret ?: &buffer) <= 0)
479 return errno_or_else(EINVAL);
480
481 return 0;
482 }
483
484 int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret) {
485 int r;
486
487 assert(s);
488
489 r = in_addr_from_string(AF_INET, s, ret);
490 if (r >= 0) {
491 if (ret_family)
492 *ret_family = AF_INET;
493 return 0;
494 }
495
496 r = in_addr_from_string(AF_INET6, s, ret);
497 if (r >= 0) {
498 if (ret_family)
499 *ret_family = AF_INET6;
500 return 0;
501 }
502
503 return -EINVAL;
504 }
505
506 unsigned char in4_addr_netmask_to_prefixlen(const struct in_addr *addr) {
507 assert(addr);
508
509 return 32U - u32ctz(be32toh(addr->s_addr));
510 }
511
512 struct in_addr* in4_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char prefixlen) {
513 assert(addr);
514 assert(prefixlen <= 32);
515
516 /* Shifting beyond 32 is not defined, handle this specially. */
517 if (prefixlen == 0)
518 addr->s_addr = 0;
519 else
520 addr->s_addr = htobe32((0xffffffff << (32 - prefixlen)) & 0xffffffff);
521
522 return addr;
523 }
524
525 int in4_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen) {
526 uint8_t msb_octet = *(uint8_t*) addr;
527
528 /* addr may not be aligned, so make sure we only access it byte-wise */
529
530 assert(addr);
531 assert(prefixlen);
532
533 if (msb_octet < 128)
534 /* class A, leading bits: 0 */
535 *prefixlen = 8;
536 else if (msb_octet < 192)
537 /* class B, leading bits 10 */
538 *prefixlen = 16;
539 else if (msb_octet < 224)
540 /* class C, leading bits 110 */
541 *prefixlen = 24;
542 else
543 /* class D or E, no default prefixlen */
544 return -ERANGE;
545
546 return 0;
547 }
548
549 int in4_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mask) {
550 unsigned char prefixlen;
551 int r;
552
553 assert(addr);
554 assert(mask);
555
556 r = in4_addr_default_prefixlen(addr, &prefixlen);
557 if (r < 0)
558 return r;
559
560 in4_addr_prefixlen_to_netmask(mask, prefixlen);
561 return 0;
562 }
563
564 int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen) {
565 assert(addr);
566
567 if (family == AF_INET) {
568 struct in_addr mask;
569
570 if (!in4_addr_prefixlen_to_netmask(&mask, prefixlen))
571 return -EINVAL;
572
573 addr->in.s_addr &= mask.s_addr;
574 return 0;
575 }
576
577 if (family == AF_INET6) {
578 unsigned i;
579
580 for (i = 0; i < 16; i++) {
581 uint8_t mask;
582
583 if (prefixlen >= 8) {
584 mask = 0xFF;
585 prefixlen -= 8;
586 } else {
587 mask = 0xFF << (8 - prefixlen);
588 prefixlen = 0;
589 }
590
591 addr->in6.s6_addr[i] &= mask;
592 }
593
594 return 0;
595 }
596
597 return -EAFNOSUPPORT;
598 }
599
600 int in_addr_prefix_covers(int family,
601 const union in_addr_union *prefix,
602 unsigned char prefixlen,
603 const union in_addr_union *address) {
604
605 union in_addr_union masked_prefix, masked_address;
606 int r;
607
608 assert(prefix);
609 assert(address);
610
611 masked_prefix = *prefix;
612 r = in_addr_mask(family, &masked_prefix, prefixlen);
613 if (r < 0)
614 return r;
615
616 masked_address = *address;
617 r = in_addr_mask(family, &masked_address, prefixlen);
618 if (r < 0)
619 return r;
620
621 return in_addr_equal(family, &masked_prefix, &masked_address);
622 }
623
624 int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret) {
625 uint8_t u;
626 int r;
627
628 if (!IN_SET(family, AF_INET, AF_INET6))
629 return -EAFNOSUPPORT;
630
631 r = safe_atou8(p, &u);
632 if (r < 0)
633 return r;
634
635 if (u > FAMILY_ADDRESS_SIZE(family) * 8)
636 return -ERANGE;
637
638 *ret = u;
639 return 0;
640 }
641
642 int in_addr_prefix_from_string(
643 const char *p,
644 int family,
645 union in_addr_union *ret_prefix,
646 unsigned char *ret_prefixlen) {
647
648 _cleanup_free_ char *str = NULL;
649 union in_addr_union buffer;
650 const char *e, *l;
651 unsigned char k;
652 int r;
653
654 assert(p);
655
656 if (!IN_SET(family, AF_INET, AF_INET6))
657 return -EAFNOSUPPORT;
658
659 e = strchr(p, '/');
660 if (e) {
661 str = strndup(p, e - p);
662 if (!str)
663 return -ENOMEM;
664
665 l = str;
666 } else
667 l = p;
668
669 r = in_addr_from_string(family, l, &buffer);
670 if (r < 0)
671 return r;
672
673 if (e) {
674 r = in_addr_parse_prefixlen(family, e+1, &k);
675 if (r < 0)
676 return r;
677 } else
678 k = FAMILY_ADDRESS_SIZE(family) * 8;
679
680 if (ret_prefix)
681 *ret_prefix = buffer;
682 if (ret_prefixlen)
683 *ret_prefixlen = k;
684
685 return 0;
686 }
687
688 int in_addr_prefix_from_string_auto_internal(
689 const char *p,
690 InAddrPrefixLenMode mode,
691 int *ret_family,
692 union in_addr_union *ret_prefix,
693 unsigned char *ret_prefixlen) {
694
695 _cleanup_free_ char *str = NULL;
696 union in_addr_union buffer;
697 const char *e, *l;
698 unsigned char k;
699 int family, r;
700
701 assert(p);
702
703 e = strchr(p, '/');
704 if (e) {
705 str = strndup(p, e - p);
706 if (!str)
707 return -ENOMEM;
708
709 l = str;
710 } else
711 l = p;
712
713 r = in_addr_from_string_auto(l, &family, &buffer);
714 if (r < 0)
715 return r;
716
717 if (e) {
718 r = in_addr_parse_prefixlen(family, e+1, &k);
719 if (r < 0)
720 return r;
721 } else
722 switch (mode) {
723 case PREFIXLEN_FULL:
724 k = FAMILY_ADDRESS_SIZE(family) * 8;
725 break;
726 case PREFIXLEN_REFUSE:
727 return -ENOANO; /* To distinguish this error from others. */
728 case PREFIXLEN_LEGACY:
729 if (family == AF_INET) {
730 r = in4_addr_default_prefixlen(&buffer.in, &k);
731 if (r < 0)
732 return r;
733 } else
734 k = 0;
735 break;
736 default:
737 assert_not_reached("Invalid prefixlen mode");
738 }
739
740 if (ret_family)
741 *ret_family = family;
742 if (ret_prefix)
743 *ret_prefix = buffer;
744 if (ret_prefixlen)
745 *ret_prefixlen = k;
746
747 return 0;
748
749 }
750
751 static void in_addr_data_hash_func(const struct in_addr_data *a, struct siphash *state) {
752 siphash24_compress(&a->family, sizeof(a->family), state);
753 siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(a->family), state);
754 }
755
756 static int in_addr_data_compare_func(const struct in_addr_data *x, const struct in_addr_data *y) {
757 int r;
758
759 r = CMP(x->family, y->family);
760 if (r != 0)
761 return r;
762
763 return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
764 }
765
766 DEFINE_HASH_OPS(in_addr_data_hash_ops, struct in_addr_data, in_addr_data_hash_func, in_addr_data_compare_func);
767
768 void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) {
769 assert(addr);
770
771 siphash24_compress(addr, sizeof(*addr), state);
772 }
773
774 int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) {
775 return memcmp(a, b, sizeof(*a));
776 }
777
778 DEFINE_HASH_OPS(in6_addr_hash_ops, struct in6_addr, in6_addr_hash_func, in6_addr_compare_func);