• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 28272947092

26 Jun 2026 08:38PM UTC coverage: 72.893% (+0.2%) from 72.703%
28272947092

push

github

poettering
sysupdate: Address review feedback on CheckNew varlink scaffolding

Follow-up to #42422:

 - Rename process_image() to context_process_image(), since it now
   operates on a Context object.
 - Use IN_SET() in image_type_can_sysupdate() instead of a switch.
 - Name the return parameters of context_list_components() ret_xyz, per
   our coding style.
 - Drop a redundant "else" after a return in vl_method_check_new().

9 of 11 new or added lines in 1 file covered. (81.82%)

12567 existing lines in 144 files now uncovered.

341026 of 467845 relevant lines covered (72.89%)

1339355.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.71
/src/basic/in-addr-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <arpa/inet.h>
4
#include <endian.h>
5
#include <stdio.h>
6

7
#include "alloc-util.h"
8
#include "errno-util.h"
9
#include "hash-funcs.h"
10
#include "in-addr-util.h"
11
#include "logarithm.h"
12
#include "memory-util.h"
13
#include "parse-util.h"
14
#include "random-util.h"
15
#include "siphash24.h"
16
#include "stdio-util.h"
17
#include "string-util.h"
18

19
bool in4_addr_is_null(const struct in_addr *a) {
157,479✔
20
        assert(a);
157,479✔
21

22
        return a->s_addr == 0;
157,479✔
23
}
24

25
bool in6_addr_is_null(const struct in6_addr *a) {
104,926✔
26
        assert(a);
104,926✔
27

28
        return eqzero(a->s6_addr32);
104,926✔
29
}
30

31
int in_addr_is_null(int family, const union in_addr_union *u) {
178,322✔
32
        assert(u);
178,322✔
33

34
        if (family == AF_INET)
178,322✔
35
                return in4_addr_is_null(&u->in);
81,155✔
36

37
        if (family == AF_INET6)
97,167✔
38
                return in6_addr_is_null(&u->in6);
68,730✔
39

40
        return -EAFNOSUPPORT;
41
}
42

43
bool in4_addr_is_link_local(const struct in_addr *a) {
11,950✔
44
        assert(a);
11,950✔
45

46
        return (be32toh(a->s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
11,950✔
47
}
48

49
bool in4_addr_is_link_local_dynamic(const struct in_addr *a) {
90✔
50
        assert(a);
90✔
51

52
        if (!in4_addr_is_link_local(a))
90✔
53
                return false;
54

55
        /* 169.254.0.0/24 and 169.254.255.0/24 must not be used for the dynamic IPv4LL assignment.
56
         * See RFC 3927 Section 2.1:
57
         * The IPv4 prefix 169.254/16 is registered with the IANA for this purpose. The first 256 and last
58
         * 256 addresses in the 169.254/16 prefix are reserved for future use and MUST NOT be selected by a
59
         * host using this dynamic configuration mechanism. */
60
        return !IN_SET(be32toh(a->s_addr) & 0x0000FF00U, 0x0000U, 0xFF00U);
89✔
61
}
62

63
bool in6_addr_is_link_local(const struct in6_addr *a) {
6,588✔
64
        assert(a);
6,588✔
65

66
        return (a->s6_addr32[0] & htobe32(0xffc00000)) == htobe32(0xfe800000);
6,588✔
67
}
68

69
int in_addr_is_link_local(int family, const union in_addr_union *u) {
6,707✔
70
        assert(u);
6,707✔
71

72
        if (family == AF_INET)
6,707✔
73
                return in4_addr_is_link_local(&u->in);
4,659✔
74

75
        if (family == AF_INET6)
2,048✔
76
                return in6_addr_is_link_local(&u->in6);
2,048✔
77

78
        return -EAFNOSUPPORT;
79
}
80

81
bool in6_addr_is_link_local_all_nodes(const struct in6_addr *a) {
2✔
82
        assert(a);
2✔
83

84
        /* ff02::1 */
85
        return be32toh(a->s6_addr32[0]) == UINT32_C(0xff020000) &&
2✔
86
                a->s6_addr32[1] == 0 &&
×
87
                a->s6_addr32[2] == 0 &&
2✔
88
                be32toh(a->s6_addr32[3]) == UINT32_C(0x00000001);
×
89
}
90

91
bool in4_addr_is_multicast(const struct in_addr *a) {
29✔
92
        assert(a);
29✔
93

94
        return IN_MULTICAST(be32toh(a->s_addr));
29✔
95
}
96

97
bool in6_addr_is_multicast(const struct in6_addr *a) {
209✔
98
        assert(a);
209✔
99

100
        return a->s6_addr[0] == 0xff;
209✔
101
}
102

103
int in_addr_is_multicast(int family, const union in_addr_union *u) {
15✔
104
        assert(u);
15✔
105

106
        if (family == AF_INET)
15✔
107
                return in4_addr_is_multicast(&u->in);
6✔
108

109
        if (family == AF_INET6)
9✔
110
                return in6_addr_is_multicast(&u->in6);
9✔
111

112
        return -EAFNOSUPPORT;
113
}
114

115
bool in4_addr_is_local_multicast(const struct in_addr *a) {
2✔
116
        assert(a);
2✔
117

118
        return (be32toh(a->s_addr) & UINT32_C(0xffffff00)) == UINT32_C(0xe0000000);
2✔
119
}
120

121
bool in4_addr_is_localhost(const struct in_addr *a) {
23,468✔
122
        assert(a);
23,468✔
123

124
        /* All of 127.x.x.x is localhost. */
125
        return (be32toh(a->s_addr) & UINT32_C(0xFF000000)) == UINT32_C(127) << 24;
23,468✔
126
}
127

128
bool in4_addr_is_non_local(const struct in_addr *a) {
876✔
129
        /* Whether the address is not null and not localhost.
130
         *
131
         * As such, it is suitable to configure as DNS/NTP server from DHCP. */
132
        return !in4_addr_is_null(a) &&
1,752✔
133
               !in4_addr_is_localhost(a);
876✔
134
}
135

136
static bool in6_addr_is_loopback(const struct in6_addr *a) {
15,182✔
137
        return memcmp(a, &(struct in6_addr) IN6ADDR_LOOPBACK_INIT, sizeof(struct in6_addr)) == 0;
15,182✔
138
}
139

140
int in_addr_is_localhost(int family, const union in_addr_union *u) {
34,489✔
141
        assert(u);
34,489✔
142

143
        if (family == AF_INET)
34,489✔
144
                return in4_addr_is_localhost(&u->in);
19,318✔
145

146
        if (family == AF_INET6)
15,171✔
147
                return in6_addr_is_loopback(&u->in6);
15,171✔
148

149
        return -EAFNOSUPPORT;
150
}
151

152
int in_addr_is_localhost_one(int family, const union in_addr_union *u) {
24✔
153
        assert(u);
24✔
154

155
        if (family == AF_INET)
24✔
156
                /* 127.0.0.1 */
157
                return be32toh(u->in.s_addr) == UINT32_C(0x7F000001);
13✔
158

159
        if (family == AF_INET6)
11✔
160
                return in6_addr_is_loopback(&u->in6);
11✔
161

162
        return -EAFNOSUPPORT;
163
}
164

165
bool in6_addr_is_ipv4_mapped_address(const struct in6_addr *a) {
5✔
166
        assert(a);
5✔
167

168
        return a->s6_addr32[0] == 0 &&
6✔
169
                a->s6_addr32[1] == 0 &&
5✔
170
                a->s6_addr32[2] == htobe32(UINT32_C(0x0000ffff));
1✔
171
}
172

173
bool in4_addr_equal(const struct in_addr *a, const struct in_addr *b) {
119,976✔
174
        assert(a);
119,976✔
175
        assert(b);
119,976✔
176

177
        return a->s_addr == b->s_addr;
119,976✔
178
}
179

180
bool in6_addr_equal(const struct in6_addr *a, const struct in6_addr *b) {
16,742✔
181
        assert(a);
16,742✔
182
        assert(b);
16,742✔
183

184
        return memcmp(a, b, sizeof(struct in6_addr)) == 0;
16,742✔
185
}
186

187
int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b) {
122,316✔
188
        assert(a);
122,316✔
189
        assert(b);
122,316✔
190

191
        if (family == AF_INET)
122,316✔
192
                return in4_addr_equal(&a->in, &b->in);
111,485✔
193

194
        if (family == AF_INET6)
10,831✔
195
                return in6_addr_equal(&a->in6, &b->in6);
10,831✔
196

197
        return -EAFNOSUPPORT;
198
}
199

200
bool in4_addr_prefix_intersect(
849✔
201
                const struct in_addr *a,
202
                unsigned aprefixlen,
203
                const struct in_addr *b,
204
                unsigned bprefixlen) {
205

206
        assert(a);
849✔
207
        assert(b);
849✔
208

209
        unsigned m = MIN3(aprefixlen, bprefixlen, (unsigned) (sizeof(struct in_addr) * 8));
849✔
210
        if (m == 0)
849✔
211
                return true; /* Let's return earlier, to avoid shift by 32. */
212

213
        uint32_t x = be32toh(a->s_addr ^ b->s_addr);
847✔
214
        uint32_t n = 0xFFFFFFFFUL << (32 - m);
847✔
215
        return (x & n) == 0;
847✔
216
}
217

218
bool in6_addr_prefix_intersect(
521✔
219
                const struct in6_addr *a,
220
                unsigned aprefixlen,
221
                const struct in6_addr *b,
222
                unsigned bprefixlen) {
223

224
        assert(a);
521✔
225
        assert(b);
521✔
226

227
        unsigned m = MIN3(aprefixlen, bprefixlen, (unsigned) (sizeof(struct in6_addr) * 8));
521✔
228
        if (m == 0)
521✔
229
                return true;
230

231
        for (size_t i = 0; i < sizeof(struct in6_addr); i++) {
841✔
232
                uint8_t x = a->s6_addr[i] ^ b->s6_addr[i];
841✔
233
                uint8_t n = m < 8 ? (0xFF << (8 - m)) : 0xFF;
841✔
234
                if ((x & n) != 0)
841✔
235
                        return false;
236

237
                if (m <= 8)
341✔
238
                        break;
239

240
                m -= 8;
322✔
241
        }
242

243
        return true;
244
}
245

246
int in_addr_prefix_intersect(
1,338✔
247
                int family,
248
                const union in_addr_union *a,
249
                unsigned aprefixlen,
250
                const union in_addr_union *b,
251
                unsigned bprefixlen) {
252

253
        assert(a);
1,338✔
254
        assert(b);
1,338✔
255

256
        /* Checks whether there are any addresses that are in both networks. */
257

258
        if (family == AF_INET)
1,338✔
259
                return in4_addr_prefix_intersect(&a->in, aprefixlen, &b->in, bprefixlen);
849✔
260

261
        if (family == AF_INET6)
489✔
262
                return in6_addr_prefix_intersect(&a->in6, aprefixlen, &b->in6, bprefixlen);
489✔
263

264
        return -EAFNOSUPPORT;
265
}
266

267
int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen) {
15✔
268
        assert(u);
15✔
269

270
        /* Increases the network part of an address by one. Returns 0 if that succeeds, or -ERANGE if
271
         * this overflows. */
272

273
        return in_addr_prefix_nth(family, u, prefixlen, 1);
15✔
274
}
275

276
/*
277
 * Calculates the nth prefix of size prefixlen starting from the address denoted by u.
278
 *
279
 * On success 0 will be returned and the calculated prefix will be available in
280
 * u. In case the calculation cannot be performed (invalid prefix length,
281
 * overflows would occur) -ERANGE is returned. If the address family given isn't
282
 * supported -EAFNOSUPPORT will be returned.
283
 *
284
 * Examples:
285
 *   - in_addr_prefix_nth(AF_INET, 192.168.0.0, 24, 2), returns 0, writes 192.168.2.0 to u
286
 *   - in_addr_prefix_nth(AF_INET, 192.168.0.0, 24, 0), returns 0, no data written
287
 *   - in_addr_prefix_nth(AF_INET, 255.255.255.0, 24, 1), returns -ERANGE, no data written
288
 *   - in_addr_prefix_nth(AF_INET, 255.255.255.0, 0, 1), returns -ERANGE, no data written
289
 *   - in_addr_prefix_nth(AF_INET6, 2001:db8, 64, 0xff00) returns 0, writes 2001:0db8:0000:ff00:: to u
290
 */
291
int in_addr_prefix_nth(int family, union in_addr_union *u, unsigned prefixlen, uint64_t nth) {
140✔
292
        assert(u);
140✔
293

294
        if (prefixlen <= 0)
140✔
295
                return -ERANGE;
296

297
        if (family == AF_INET) {
138✔
298
                uint32_t c, n, t;
19✔
299

300
                if (prefixlen > 32)
19✔
301
                        return -ERANGE;
302

303
                c = be32toh(u->in.s_addr);
19✔
304

305
                t = nth << (32 - prefixlen);
19✔
306

307
                /* Check for wrap */
308
                if (c > UINT32_MAX - t)
19✔
309
                        return -ERANGE;
310

311
                n = c + t;
16✔
312

313
                n &= UINT32_C(0xFFFFFFFF) << (32 - prefixlen);
16✔
314
                u->in.s_addr = htobe32(n);
16✔
315
                return 0;
16✔
316
        }
317

318
        if (family == AF_INET6) {
119✔
319
                bool overflow = false;
119✔
320

321
                if (prefixlen > 128)
119✔
322
                        return -ERANGE;
323

324
                for (unsigned i = 16; i > 0; i--) {
2,023✔
325
                        unsigned t, j = i - 1, p = j * 8;
1,904✔
326

327
                        if (p >= prefixlen) {
1,904✔
328
                                u->in6.s6_addr[j] = 0;
885✔
329
                                continue;
885✔
330
                        }
331

332
                        if (prefixlen - p < 8) {
1,019✔
333
                                u->in6.s6_addr[j] &= 0xff << (8 - (prefixlen - p));
14✔
334
                                t = u->in6.s6_addr[j] + ((nth & 0xff) << (8 - (prefixlen - p)));
14✔
335
                                nth >>= prefixlen - p;
14✔
336
                        } else {
337
                                t = u->in6.s6_addr[j] + (nth & 0xff) + overflow;
1,005✔
338
                                nth >>= 8;
1,005✔
339
                        }
340

341
                        overflow = t > UINT8_MAX;
1,019✔
342
                        u->in6.s6_addr[j] = (uint8_t) (t & 0xff);
1,019✔
343
                }
344

345
                if (overflow || nth != 0)
119✔
346
                        return -ERANGE;
347

348
                return 0;
115✔
349
        }
350

351
        return -EAFNOSUPPORT;
352
}
353

354
int in_addr_random_prefix(
43✔
355
                int family,
356
                union in_addr_union *u,
357
                unsigned prefixlen_fixed_part,
358
                unsigned prefixlen) {
359

360
        assert(u);
43✔
361

362
        /* Random network part of an address by one. */
363

364
        if (prefixlen <= 0)
43✔
365
                return 0;
366

367
        if (family == AF_INET) {
43✔
368
                uint32_t c, n;
24✔
369

370
                if (prefixlen_fixed_part > 32)
24✔
371
                        prefixlen_fixed_part = 32;
×
372
                if (prefixlen > 32)
24✔
UNCOV
373
                        prefixlen = 32;
×
374
                if (prefixlen_fixed_part >= prefixlen)
24✔
375
                        return -EINVAL;
24✔
376

377
                c = be32toh(u->in.s_addr);
24✔
378
                c &= ((UINT32_C(1) << prefixlen_fixed_part) - 1) << (32 - prefixlen_fixed_part);
24✔
379

380
                random_bytes(&n, sizeof(n));
24✔
381
                n &= ((UINT32_C(1) << (prefixlen - prefixlen_fixed_part)) - 1) << (32 - prefixlen);
24✔
382

383
                u->in.s_addr = htobe32(n | c);
24✔
384
                return 1;
24✔
385
        }
386

387
        if (family == AF_INET6) {
19✔
388
                struct in6_addr n;
19✔
389
                unsigned i, j;
19✔
390

391
                if (prefixlen_fixed_part > 128)
19✔
392
                        prefixlen_fixed_part = 128;
×
393
                if (prefixlen > 128)
19✔
UNCOV
394
                        prefixlen = 128;
×
395
                if (prefixlen_fixed_part >= prefixlen)
19✔
396
                        return -EINVAL;
19✔
397

398
                random_bytes(&n, sizeof(n));
19✔
399

400
                for (i = 0; i < 16; i++) {
323✔
401
                        uint8_t mask_fixed_part = 0, mask = 0;
304✔
402

403
                        if (i < (prefixlen_fixed_part + 7) / 8) {
304✔
404
                                if (i < prefixlen_fixed_part / 8)
20✔
405
                                        mask_fixed_part = 0xffu;
406
                                else {
UNCOV
407
                                        j = prefixlen_fixed_part % 8;
×
UNCOV
408
                                        mask_fixed_part = ((UINT8_C(1) << (j + 1)) - 1) << (8 - j);
×
409
                                }
410
                        }
411

412
                        if (i < (prefixlen + 7) / 8) {
304✔
413
                                if (i < prefixlen / 8)
178✔
414
                                        mask = 0xffu ^ mask_fixed_part;
162✔
415
                                else {
416
                                        j = prefixlen % 8;
16✔
417
                                        mask = (((UINT8_C(1) << (j + 1)) - 1) << (8 - j)) ^ mask_fixed_part;
16✔
418
                                }
419
                        }
420

421
                        u->in6.s6_addr[i] &= mask_fixed_part;
304✔
422
                        u->in6.s6_addr[i] |= n.s6_addr[i] & mask;
304✔
423
                }
424

425
                return 1;
426
        }
427

428
        return -EAFNOSUPPORT;
429
}
430

431
int in_addr_prefix_range(
52✔
432
                int family,
433
                const union in_addr_union *in,
434
                unsigned prefixlen,
435
                union in_addr_union *ret_start,
436
                union in_addr_union *ret_end) {
437

438
        union in_addr_union start, end;
52✔
439
        int r;
52✔
440

441
        assert(in);
52✔
442

443
        if (!IN_SET(family, AF_INET, AF_INET6))
52✔
444
                return -EAFNOSUPPORT;
52✔
445

446
        if (ret_start) {
52✔
447
                start = *in;
52✔
448
                r = in_addr_prefix_nth(family, &start, prefixlen, 0);
52✔
449
                if (r < 0)
52✔
450
                        return r;
451
        }
452

453
        if (ret_end) {
52✔
454
                end = *in;
52✔
455
                r = in_addr_prefix_nth(family, &end, prefixlen, 1);
52✔
456
                if (r < 0)
52✔
457
                        return r;
458
        }
459

460
        if (ret_start)
52✔
461
                *ret_start = start;
52✔
462
        if (ret_end)
52✔
463
                *ret_end = end;
52✔
464

465
        return 0;
466
}
467

468
int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
10,976✔
469
        _cleanup_free_ char *x = NULL;
10,976✔
470
        size_t l;
10,976✔
471

472
        assert(u);
10,976✔
473
        assert(ret);
10,976✔
474

475
        if (family == AF_INET)
10,976✔
476
                l = INET_ADDRSTRLEN;
477
        else if (family == AF_INET6)
1,670✔
478
                l = INET6_ADDRSTRLEN;
479
        else
480
                return -EAFNOSUPPORT;
481

482
        x = new(char, l);
10,976✔
483
        if (!x)
10,976✔
484
                return -ENOMEM;
485

486
        errno = 0;
10,976✔
487
        if (!typesafe_inet_ntop(family, u, x, l))
10,976✔
488
                return errno_or_else(EINVAL);
10,976✔
489

490
        *ret = TAKE_PTR(x);
10,976✔
491
        return 0;
10,976✔
492
}
493

494
const char* typesafe_inet_ntop(int family, const union in_addr_union *a, char *buf, size_t len) {
481,745✔
495
        return inet_ntop(family, a, buf, len);
481,745✔
496
}
497

498
const char* typesafe_inet_ntop4(const struct in_addr *a, char *buf, size_t len) {
5,766✔
499
        return inet_ntop(AF_INET, a, buf, len);
5,766✔
500
}
501

502
const char* typesafe_inet_ntop6(const struct in6_addr *a, char *buf, size_t len) {
1,544✔
503
        return inet_ntop(AF_INET6, a, buf, len);
1,544✔
504
}
505

506
int in_addr_prefix_to_string(
416,020✔
507
                int family,
508
                const union in_addr_union *u,
509
                unsigned prefixlen,
510
                char *buf,
511
                size_t buf_len) {
512

513
        assert(u);
416,020✔
514
        assert(buf);
416,020✔
515

516
        if (!IN_SET(family, AF_INET, AF_INET6))
416,020✔
517
                return -EAFNOSUPPORT;
518

519
        errno = 0;
416,020✔
520
        if (!typesafe_inet_ntop(family, u, buf, buf_len))
416,020✔
UNCOV
521
                return errno_or_else(ENOSPC);
×
522

523
        size_t l = strlen(buf);
416,020✔
524
        if (!snprintf_ok(buf + l, buf_len - l, "/%u", prefixlen))
416,020✔
UNCOV
525
                return -ENOSPC;
×
526
        return 0;
527
}
528

529
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) {
1,881✔
530
        _cleanup_free_ char *ip_str = NULL, *x = NULL;
1,881✔
531
        int r;
1,881✔
532

533
        assert(IN_SET(family, AF_INET, AF_INET6));
1,881✔
534
        assert(u);
1,881✔
535
        assert(ret);
1,881✔
536

537
        /* Much like in_addr_to_string(), but optionally appends the zone interface index to the address, to properly
538
         * handle IPv6 link-local addresses. */
539

540
        r = in_addr_to_string(family, u, &ip_str);
1,881✔
541
        if (r < 0)
1,881✔
542
                return r;
543

544
        if (family == AF_INET6) {
1,881✔
545
                r = in_addr_is_link_local(family, u);
839✔
546
                if (r < 0)
839✔
547
                        return r;
548
                if (r == 0)
839✔
549
                        ifindex = 0;
782✔
550
        } else
551
                ifindex = 0; /* For IPv4 address, ifindex is always ignored. */
552

553
        if (port == 0 && ifindex == 0 && isempty(server_name)) {
1,881✔
554
                *ret = TAKE_PTR(ip_str);
1,544✔
555
                return 0;
1,544✔
556
        }
557

558
        const char *separator = isempty(server_name) ? "" : "#";
337✔
559
        server_name = strempty(server_name);
337✔
560

561
        if (port > 0) {
337✔
562
                if (family == AF_INET6) {
29✔
563
                        if (ifindex > 0)
16✔
564
                                x = asprintf_safe("[%s]:%"PRIu16"%%%i%s%s", ip_str, port, ifindex, separator, server_name);
10✔
565
                        else
566
                                x = asprintf_safe("[%s]:%"PRIu16"%s%s", ip_str, port, separator, server_name);
6✔
567
                } else
568
                        x = asprintf_safe("%s:%"PRIu16"%s%s", ip_str, port, separator, server_name);
13✔
569
        } else {
570
                if (ifindex > 0)
308✔
571
                        x = asprintf_safe("%s%%%i%s%s", ip_str, ifindex, separator, server_name);
32✔
572
                else
573
                        x = strjoin(ip_str, separator, server_name);
276✔
574
        }
575
        if (!x)
337✔
576
                return -ENOMEM;
577

578
        *ret = TAKE_PTR(x);
337✔
579
        return 0;
337✔
580
}
581

582
int in_addr_from_string(int family, const char *s, union in_addr_union *ret) {
216,264✔
583
        union in_addr_union buffer;
216,264✔
584
        assert(s);
216,264✔
585

586
        if (!IN_SET(family, AF_INET, AF_INET6))
216,264✔
587
                return -EAFNOSUPPORT;
216,264✔
588

589
        errno = 0;
216,264✔
590
        if (inet_pton(family, s, ret ?: &buffer) <= 0)
216,820✔
591
                return errno_or_else(EINVAL);
69,615✔
592

593
        return 0;
594
}
595

596
int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret) {
141,048✔
597
        int r;
141,048✔
598

599
        assert(s);
141,048✔
600

601
        r = in_addr_from_string(AF_INET, s, ret);
141,048✔
602
        if (r >= 0) {
141,048✔
603
                if (ret_family)
73,025✔
604
                        *ret_family = AF_INET;
72,795✔
605
                return 0;
606
        }
607

608
        r = in_addr_from_string(AF_INET6, s, ret);
68,023✔
609
        if (r >= 0) {
68,023✔
610
                if (ret_family)
67,724✔
611
                        *ret_family = AF_INET6;
67,710✔
612
                return 0;
613
        }
614

615
        return -EINVAL;
616
}
617

618
unsigned char in4_addr_netmask_to_prefixlen(const struct in_addr *addr) {
431✔
619
        assert(addr);
431✔
620

621
        return 32U - u32ctz(be32toh(addr->s_addr));
431✔
622
}
623

624
/* Calculate an IPv4 netmask from prefix length, for example /8 -> 255.0.0.0. */
625
struct in_addr* in4_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char prefixlen) {
187,830✔
626
        assert(addr);
187,830✔
627
        assert(prefixlen <= 32);
187,830✔
628

629
        /* Shifting beyond 32 is not defined, handle this specially. */
630
        if (prefixlen == 0)
187,830✔
631
                addr->s_addr = 0;
3,413✔
632
        else
633
                addr->s_addr = htobe32((0xffffffff << (32 - prefixlen)) & 0xffffffff);
184,417✔
634

635
        return addr;
187,830✔
636
}
637

638
/* Calculate an IPv6 netmask from prefix length, for example /16 -> ffff::. */
639
struct in6_addr* in6_addr_prefixlen_to_netmask(struct in6_addr *addr, unsigned char prefixlen) {
165✔
640
        assert(addr);
165✔
641
        assert(prefixlen <= 128);
165✔
642

643
        for (unsigned i = 0; i < 16; i++) {
2,805✔
644
                uint8_t mask;
2,640✔
645

646
                if (prefixlen >= 8) {
2,640✔
647
                        mask = 0xFF;
1,264✔
648
                        prefixlen -= 8;
1,264✔
649
                } else if (prefixlen > 0) {
1,376✔
650
                        mask = 0xFF << (8 - prefixlen);
112✔
651
                        prefixlen = 0;
112✔
652
                } else {
653
                        assert(prefixlen == 0);
654
                        mask = 0;
655
                }
656

657
                addr->s6_addr[i] = mask;
2,640✔
658
        }
659

660
        return addr;
165✔
661
}
662

663
/* Calculate an IPv4 or IPv6 netmask from prefix length, for example /8 -> 255.0.0.0 or /16 -> ffff::. */
664
int in_addr_prefixlen_to_netmask(int family, union in_addr_union *addr, unsigned char prefixlen) {
226✔
665
        assert(addr);
226✔
666

667
        switch (family) {
226✔
668
        case AF_INET:
61✔
669
                in4_addr_prefixlen_to_netmask(&addr->in, prefixlen);
61✔
670
                return 0;
61✔
671
        case AF_INET6:
165✔
672
                in6_addr_prefixlen_to_netmask(&addr->in6, prefixlen);
165✔
673
                return 0;
165✔
674
        default:
675
                return -EAFNOSUPPORT;
676
        }
677
}
678

679
int in4_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen) {
44✔
680
        uint8_t msb_octet = *(uint8_t*) addr;
44✔
681

682
        /* addr may not be aligned, so make sure we only access it byte-wise */
683

684
        assert(addr);
44✔
685
        assert(prefixlen);
44✔
686

687
        if (msb_octet < 128)
44✔
688
                /* class A, leading bits: 0 */
689
                *prefixlen = 8;
20✔
690
        else if (msb_octet < 192)
24✔
691
                /* class B, leading bits 10 */
692
                *prefixlen = 16;
4✔
693
        else if (msb_octet < 224)
20✔
694
                /* class C, leading bits 110 */
695
                *prefixlen = 24;
20✔
696
        else
697
                /* class D or E, no default prefixlen */
698
                return -ERANGE;
699

700
        return 0;
701
}
702

703
int in4_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mask) {
×
UNCOV
704
        unsigned char prefixlen;
×
705
        int r;
×
706

UNCOV
707
        assert(addr);
×
708
        assert(mask);
×
709

710
        r = in4_addr_default_prefixlen(addr, &prefixlen);
×
UNCOV
711
        if (r < 0)
×
712
                return r;
×
713

UNCOV
714
        in4_addr_prefixlen_to_netmask(mask, prefixlen);
×
715
        return 0;
716
}
717

718
int in4_addr_mask(struct in_addr *addr, unsigned char prefixlen) {
187,735✔
719
        struct in_addr mask;
187,735✔
720

721
        assert(addr);
187,735✔
722

723
        if (!in4_addr_prefixlen_to_netmask(&mask, prefixlen))
187,735✔
724
                return -EINVAL;
187,735✔
725

726
        addr->s_addr &= mask.s_addr;
187,735✔
727
        return 0;
187,735✔
728
}
729

730
int in6_addr_mask(struct in6_addr *addr, unsigned char prefixlen) {
143,750✔
731
        unsigned i;
143,750✔
732

733
        assert(addr);
143,750✔
734

735
        for (i = 0; i < 16; i++) {
2,443,750✔
736
                uint8_t mask;
2,300,000✔
737

738
                if (prefixlen >= 8) {
2,300,000✔
739
                        mask = 0xFF;
430,848✔
740
                        prefixlen -= 8;
430,848✔
741
                } else if (prefixlen > 0) {
1,869,152✔
742
                        mask = 0xFF << (8 - prefixlen);
258✔
743
                        prefixlen = 0;
258✔
744
                } else {
745
                        assert(prefixlen == 0);
746
                        mask = 0;
747
                }
748

749
                addr->s6_addr[i] &= mask;
2,300,000✔
750
        }
751

752
        return 0;
143,750✔
753
}
754

755
int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen) {
270,350✔
756
        assert(addr);
270,350✔
757

758
        switch (family) {
270,350✔
759
        case AF_INET:
135,173✔
760
                return in4_addr_mask(&addr->in, prefixlen);
135,173✔
761
        case AF_INET6:
135,177✔
762
                return in6_addr_mask(&addr->in6, prefixlen);
135,177✔
763
        default:
764
                return -EAFNOSUPPORT;
765
        }
766
}
767

768
int in4_addr_prefix_covers_full(
3,158✔
769
                const struct in_addr *prefix,
770
                unsigned char prefixlen,
771
                const struct in_addr *address,
772
                unsigned char address_prefixlen) {
773

774
        struct in_addr masked_prefix, masked_address;
3,158✔
775
        int r;
3,158✔
776

777
        assert(prefix);
3,158✔
778
        assert(address);
3,158✔
779

780
        if (prefixlen > address_prefixlen)
3,158✔
781
                return false;
3,158✔
782

783
        masked_prefix = *prefix;
2,630✔
784
        r = in4_addr_mask(&masked_prefix, prefixlen);
2,630✔
785
        if (r < 0)
2,630✔
786
                return r;
787

788
        masked_address = *address;
2,630✔
789
        r = in4_addr_mask(&masked_address, prefixlen);
2,630✔
790
        if (r < 0)
2,630✔
791
                return r;
792

793
        return in4_addr_equal(&masked_prefix, &masked_address);
2,630✔
794
}
795

796
int in6_addr_prefix_covers_full(
4,033✔
797
                const struct in6_addr *prefix,
798
                unsigned char prefixlen,
799
                const struct in6_addr *address,
800
                unsigned char address_prefixlen) {
801

802
        struct in6_addr masked_prefix, masked_address;
4,033✔
803
        int r;
4,033✔
804

805
        assert(prefix);
4,033✔
806
        assert(address);
4,033✔
807

808
        if (prefixlen > address_prefixlen)
4,033✔
809
                return false;
4,033✔
810

811
        masked_prefix = *prefix;
4,033✔
812
        r = in6_addr_mask(&masked_prefix, prefixlen);
4,033✔
813
        if (r < 0)
4,033✔
814
                return r;
815

816
        masked_address = *address;
4,033✔
817
        r = in6_addr_mask(&masked_address, prefixlen);
4,033✔
818
        if (r < 0)
4,033✔
819
                return r;
820

821
        return in6_addr_equal(&masked_prefix, &masked_address);
4,033✔
822
}
823

824
int in_addr_prefix_covers_full(
6,918✔
825
                int family,
826
                const union in_addr_union *prefix,
827
                unsigned char prefixlen,
828
                const union in_addr_union *address,
829
                unsigned char address_prefixlen) {
830

831
        assert(prefix);
6,918✔
832
        assert(address);
6,918✔
833

834
        switch (family) {
6,918✔
835
        case AF_INET:
2,938✔
836
                return in4_addr_prefix_covers_full(&prefix->in, prefixlen, &address->in, address_prefixlen);
2,938✔
837
        case AF_INET6:
3,980✔
838
                return in6_addr_prefix_covers_full(&prefix->in6, prefixlen, &address->in6, address_prefixlen);
3,980✔
839
        default:
840
                return -EAFNOSUPPORT;
841
        }
842
}
843

844
int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret) {
141,077✔
845
        uint8_t u;
141,077✔
846
        int r;
141,077✔
847

848
        assert(ret);
141,077✔
849

850
        if (!IN_SET(family, AF_INET, AF_INET6))
141,077✔
851
                return -EAFNOSUPPORT;
141,077✔
852

853
        r = safe_atou8(p, &u);
141,077✔
854
        if (r < 0)
141,077✔
855
                return r;
856

857
        if (u > FAMILY_ADDRESS_SIZE(family) * 8)
141,073✔
858
                return -ERANGE;
859

860
        *ret = u;
141,069✔
861
        return 0;
141,069✔
862
}
863

864
int in_addr_prefix_from_string(
1,441✔
865
                const char *p,
866
                int family,
867
                union in_addr_union *ret_prefix,
868
                unsigned char *ret_prefixlen) {
869

870
        _cleanup_free_ char *str = NULL;
1,441✔
871
        union in_addr_union buffer;
1,441✔
872
        const char *e, *l;
1,441✔
873
        unsigned char k;
1,441✔
874
        int r;
1,441✔
875

876
        assert(p);
1,441✔
877

878
        if (!IN_SET(family, AF_INET, AF_INET6))
1,441✔
879
                return -EAFNOSUPPORT;
880

881
        e = strchr(p, '/');
1,441✔
882
        if (e) {
1,441✔
883
                str = strndup(p, e - p);
1,425✔
884
                if (!str)
1,425✔
885
                        return -ENOMEM;
886

887
                l = str;
888
        } else
889
                l = p;
890

891
        r = in_addr_from_string(family, l, &buffer);
1,441✔
892
        if (r < 0)
1,441✔
893
                return r;
894

895
        if (e) {
1,433✔
896
                r = in_addr_parse_prefixlen(family, e+1, &k);
1,420✔
897
                if (r < 0)
1,420✔
898
                        return r;
899
        } else
900
                k = FAMILY_ADDRESS_SIZE(family) * 8;
13✔
901

902
        if (ret_prefix)
1,429✔
903
                *ret_prefix = buffer;
1,429✔
904
        if (ret_prefixlen)
1,429✔
905
                *ret_prefixlen = k;
1,429✔
906

907
        return 0;
908
}
909

910
int in_addr_prefix_from_string_auto_full(
139,960✔
911
                const char *p,
912
                InAddrPrefixLenMode mode,
913
                int *ret_family,
914
                union in_addr_union *ret_prefix,
915
                unsigned char *ret_prefixlen) {
916

917
        _cleanup_free_ char *str = NULL;
139,960✔
918
        union in_addr_union buffer;
139,960✔
919
        const char *e, *l;
139,960✔
920
        unsigned char k;
139,960✔
921
        int family, r;
139,960✔
922

923
        assert(p);
139,960✔
924

925
        e = strchr(p, '/');
139,960✔
926
        if (e) {
139,960✔
927
                str = strndup(p, e - p);
139,661✔
928
                if (!str)
139,661✔
929
                        return -ENOMEM;
930

931
                l = str;
932
        } else
933
                l = p;
934

935
        r = in_addr_from_string_auto(l, &family, &buffer);
139,960✔
936
        if (r < 0)
139,960✔
937
                return r;
938

939
        if (e) {
139,929✔
940
                r = in_addr_parse_prefixlen(family, e+1, &k);
139,657✔
941
                if (r < 0)
139,657✔
942
                        return r;
943
        } else
944
                switch (mode) {
272✔
945
                case PREFIXLEN_FULL:
256✔
946
                        k = FAMILY_ADDRESS_SIZE(family) * 8;
256✔
947
                        break;
256✔
948
                case PREFIXLEN_REFUSE:
949
                        return -ENOANO; /* To distinguish this error from others. */
UNCOV
950
                default:
×
UNCOV
951
                        assert_not_reached();
×
952
                }
953

954
        if (ret_family)
139,909✔
955
                *ret_family = family;
139,909✔
956
        if (ret_prefix)
139,909✔
957
                *ret_prefix = buffer;
139,909✔
958
        if (ret_prefixlen)
139,909✔
959
                *ret_prefixlen = k;
139,909✔
960

961
        return 0;
962
}
963

964
void in_addr_hash_func(const union in_addr_union *u, int family, struct siphash *state) {
842,160✔
965
        assert(u);
842,160✔
966
        assert(state);
842,160✔
967

968
        siphash24_compress(u->bytes, FAMILY_ADDRESS_SIZE(family), state);
842,160✔
969
}
842,160✔
970

971
void in_addr_data_hash_func(const struct in_addr_data *a, struct siphash *state) {
747✔
972
        assert(a);
747✔
973
        assert(state);
747✔
974

975
        siphash24_compress_typesafe(a->family, state);
747✔
976
        in_addr_hash_func(&a->address, a->family, state);
747✔
977
}
747✔
978

979
int in_addr_data_compare_func(const struct in_addr_data *x, const struct in_addr_data *y) {
353✔
980
        int r;
353✔
981

982
        assert(x);
353✔
983
        assert(y);
353✔
984

985
        r = CMP(x->family, y->family);
353✔
986
        if (r != 0)
279✔
987
                return r;
988

989
        return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
253✔
990
}
991

992
DEFINE_HASH_OPS(
993
        in_addr_data_hash_ops,
994
        struct in_addr_data,
995
        in_addr_data_hash_func,
996
        in_addr_data_compare_func);
997

998
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
181✔
999
        in_addr_data_hash_ops_free,
1000
        struct in_addr_data,
1001
        in_addr_data_hash_func,
1002
        in_addr_data_compare_func,
1003
        free);
1004

1005
void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) {
486✔
1006
        assert(addr);
486✔
1007
        assert(state);
486✔
1008

1009
        siphash24_compress_typesafe(*addr, state);
486✔
1010
}
486✔
1011

1012
int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) {
199✔
1013
        assert(a);
199✔
1014
        assert(b);
199✔
1015

1016
        return memcmp(a, b, sizeof(*a));
199✔
1017
}
1018

1019
DEFINE_HASH_OPS(
1020
        in6_addr_hash_ops,
1021
        struct in6_addr,
1022
        in6_addr_hash_func,
1023
        in6_addr_compare_func);
1024

1025
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
5✔
1026
        in6_addr_hash_ops_free,
1027
        struct in6_addr,
1028
        in6_addr_hash_func,
1029
        in6_addr_compare_func,
1030
        free);
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc