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