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

systemd / systemd / 29461261567

15 Jul 2026 04:59PM UTC coverage: 72.983% (+0.05%) from 72.936%
29461261567

push

github

yuwata
tpm2-util: keep the measurement log's torn-write marker intact

The userspace measurement log carries a sticky-bit marker while a writer
is between updating a measurement register and appending the matching
record, so that a writer dying in between leaves the log detectably
incomplete.

However, the next successful writer used to clear the marker again after
appending its own record, erasing the evidence that an earlier writer
had died and the log is still missing a record. Keep the marker set in
that case instead; the new record is appended and synced regardless. The
marker likewise stays set if the measurement itself fails, so that any
non-clean completion remains flagged: a spurious flag on a failed but
harmless measurement is preferable to erasing evidence of a real gap,
and PCR replay stays authoritative either way.

Finally, warn when systemd-pcrlock loads a marked log, so the resulting
PCR validation failures come with a hint at their cause.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>

11 of 12 new or added lines in 2 files covered. (91.67%)

2475 existing lines in 54 files now uncovered.

346100 of 474222 relevant lines covered (72.98%)

1321758.71 hits per line

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

95.51
/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,674✔
20
        assert(a);
157,674✔
21

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

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

28
        return eqzero(a->s6_addr32);
105,525✔
29
}
30

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

34
        if (family == AF_INET)
178,376✔
35
                return in4_addr_is_null(&u->in);
80,957✔
36

37
        if (family == AF_INET6)
97,419✔
38
                return in6_addr_is_null(&u->in6);
69,238✔
39

40
        return -EAFNOSUPPORT;
41
}
42

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

46
        return (be32toh(a->s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
12,043✔
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,495✔
64
        assert(a);
6,495✔
65

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

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

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

75
        if (family == AF_INET6)
2,148✔
76
                return in6_addr_is_link_local(&u->in6);
2,148✔
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) {
36✔
92
        assert(a);
36✔
93

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

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

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

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

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

109
        if (family == AF_INET6)
14✔
110
                return in6_addr_is_multicast(&u->in6);
14✔
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,939✔
122
        assert(a);
23,939✔
123

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

128
bool in4_addr_is_non_local(const struct in_addr *a) {
882✔
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,764✔
133
               !in4_addr_is_localhost(a);
882✔
134
}
135

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

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

143
        if (family == AF_INET)
35,117✔
144
                return in4_addr_is_localhost(&u->in);
19,753✔
145

146
        if (family == AF_INET6)
15,364✔
147
                return in6_addr_is_loopback(&u->in6);
15,364✔
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,910✔
174
        assert(a);
119,910✔
175
        assert(b);
119,910✔
176

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

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

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

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

191
        if (family == AF_INET)
121,371✔
192
                return in4_addr_equal(&a->in, &b->in);
110,959✔
193

194
        if (family == AF_INET6)
10,412✔
195
                return in6_addr_equal(&a->in6, &b->in6);
10,412✔
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(
528✔
219
                const struct in6_addr *a,
220
                unsigned aprefixlen,
221
                const struct in6_addr *b,
222
                unsigned bprefixlen) {
223

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

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

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

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

240
                m -= 8;
346✔
241
        }
242

243
        return true;
244
}
245

246
int in_addr_prefix_intersect(
1,339✔
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,339✔
254
        assert(b);
1,339✔
255

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

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

261
        if (family == AF_INET6)
490✔
262
                return in6_addr_prefix_intersect(&a->in6, aprefixlen, &b->in6, bprefixlen);
490✔
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;
861✔
329
                                continue;
861✔
330
                        }
331

332
                        if (prefixlen - p < 8) {
1,043✔
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,029✔
338
                                nth >>= 8;
1,029✔
339
                        }
340

341
                        overflow = t > UINT8_MAX;
1,043✔
342
                        u->in6.s6_addr[j] = (uint8_t) (t & 0xff);
1,043✔
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✔
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✔
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 {
407
                                        j = prefixlen_fixed_part % 8;
×
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,756✔
469
        _cleanup_free_ char *x = NULL;
10,756✔
470
        size_t l;
10,756✔
471

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

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

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

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

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

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

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

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

506
int in_addr_prefix_to_string(
415,647✔
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);
415,647✔
514
        assert(buf);
415,647✔
515

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

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

523
        size_t l = strlen(buf);
415,647✔
524
        if (!snprintf_ok(buf + l, buf_len - l, "/%u", prefixlen))
415,647✔
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,908✔
530
        _cleanup_free_ char *ip_str = NULL, *x = NULL;
1,908✔
531
        int r;
1,908✔
532

533
        assert(IN_SET(family, AF_INET, AF_INET6));
1,908✔
534
        assert(u);
1,908✔
535
        assert(ret);
1,908✔
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,908✔
541
        if (r < 0)
1,908✔
542
                return r;
543

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

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

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

561
        if (port > 0) {
341✔
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)
312✔
571
                        x = asprintf_safe("%s%%%i%s%s", ip_str, ifindex, separator, server_name);
31✔
572
                else
573
                        x = strjoin(ip_str, separator, server_name);
281✔
574
        }
575
        if (!x)
341✔
576
                return -ENOMEM;
577

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

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

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

589
        errno = 0;
216,448✔
590
        if (inet_pton(family, s, ret ?: &buffer) <= 0)
216,995✔
591
                return errno_or_else(EINVAL);
69,673✔
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,095✔
597
        int r;
141,095✔
598

599
        assert(s);
141,095✔
600

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

608
        r = in_addr_from_string(AF_INET6, s, ret);
68,027✔
609
        if (r >= 0) {
68,027✔
610
                if (ret_family)
67,732✔
611
                        *ret_family = AF_INET6;
67,718✔
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) {
189,036✔
626
        assert(addr);
189,036✔
627
        assert(prefixlen <= 32);
189,036✔
628

629
        /* Shifting beyond 32 is not defined, handle this specially. */
630
        if (prefixlen == 0)
189,036✔
631
                addr->s_addr = 0;
3,431✔
632
        else
633
                addr->s_addr = htobe32((0xffffffff << (32 - prefixlen)) & 0xffffffff);
185,605✔
634

635
        return addr;
189,036✔
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) {
×
704
        unsigned char prefixlen;
×
705
        int r;
×
706

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

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

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) {
188,941✔
719
        struct in_addr mask;
188,941✔
720

721
        assert(addr);
188,941✔
722

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

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

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

733
        assert(addr);
145,460✔
734

735
        for (i = 0; i < 16; i++) {
2,472,820✔
736
                uint8_t mask;
2,327,360✔
737

738
                if (prefixlen >= 8) {
2,327,360✔
739
                        mask = 0xFF;
450,858✔
740
                        prefixlen -= 8;
450,858✔
741
                } else if (prefixlen > 0) {
1,876,502✔
742
                        mask = 0xFF << (8 - prefixlen);
270✔
743
                        prefixlen = 0;
270✔
744
                } else {
745
                        assert(prefixlen == 0);
746
                        mask = 0;
747
                }
748

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

752
        return 0;
145,460✔
753
}
754

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

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

768
int in4_addr_prefix_covers_full(
3,603✔
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,603✔
775
        int r;
3,603✔
776

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

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

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

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

793
        return in4_addr_equal(&masked_prefix, &masked_address);
3,075✔
794
}
795

796
int in6_addr_prefix_covers_full(
4,878✔
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,878✔
803
        int r;
4,878✔
804

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

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

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

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

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

824
int in_addr_prefix_covers_full(
8,190✔
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);
8,190✔
832
        assert(address);
8,190✔
833

834
        switch (family) {
8,190✔
835
        case AF_INET:
3,383✔
836
                return in4_addr_prefix_covers_full(&prefix->in, prefixlen, &address->in, address_prefixlen);
3,383✔
837
        case AF_INET6:
4,807✔
838
                return in6_addr_prefix_covers_full(&prefix->in6, prefixlen, &address->in6, address_prefixlen);
4,807✔
839
        default:
840
                return -EAFNOSUPPORT;
841
        }
842
}
843

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

848
        assert(ret);
141,127✔
849

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

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

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

860
        *ret = u;
141,119✔
861
        return 0;
141,119✔
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(
140,010✔
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;
140,010✔
918
        union in_addr_union buffer;
140,010✔
919
        const char *e, *l;
140,010✔
920
        unsigned char k;
140,010✔
921
        int family, r;
140,010✔
922

923
        assert(p);
140,010✔
924

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

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

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

939
        if (e) {
139,979✔
940
                r = in_addr_parse_prefixlen(family, e+1, &k);
139,707✔
941
                if (r < 0)
139,707✔
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. */
950
                default:
×
951
                        assert_not_reached();
×
952
                }
953

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

961
        return 0;
962
}
963

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

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

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

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

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

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

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

989
        return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
288✔
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(
198✔
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) {
450✔
1006
        assert(addr);
450✔
1007
        assert(state);
450✔
1008

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

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

1016
        return memcmp(a, b, sizeof(*a));
161✔
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

UNCOV
1025
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
×
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 TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc