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