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