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

systemd / systemd / 14766779411

30 Apr 2025 04:55PM UTC coverage: 72.225% (-0.06%) from 72.282%
14766779411

push

github

web-flow
wait-online: handle varlink connection errors while waiting for DNS (#37283)

Currently, if systemd-networkd-wait-online is started with --dns, and
systemd-resolved is not running, it will exit with an error right away.
Similarly, if systemd-resolved is restarted while waiting for DNS
configuration, systemd-networkd-wait-online will not attempt to
re-connect, and will potentially never see subsequent DNS
configurations.

Improve this by adding socket units for the systemd-resolved varlink
servers, and re-establish the connection in systemd-networkd-wait-online
when we receive `SD_VARLINK_ERROR_DISCONNECTED`.

8 of 16 new or added lines in 2 files covered. (50.0%)

5825 existing lines in 217 files now uncovered.

297168 of 411450 relevant lines covered (72.22%)

695892.62 hits per line

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

86.98
/src/network/networkd-serialize.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include "af-list.h"
4
#include "daemon-util.h"
5
#include "fd-util.h"
6
#include "fileio.h"
7
#include "iovec-util.h"
8
#include "json-util.h"
9
#include "memfd-util.h"
10
#include "networkd-address.h"
11
#include "networkd-json.h"
12
#include "networkd-link.h"
13
#include "networkd-manager.h"
14
#include "networkd-nexthop.h"
15
#include "networkd-route.h"
16
#include "networkd-serialize.h"
17

18
int manager_serialize(Manager *manager) {
417✔
19
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL, *array = NULL;
451✔
20
        int r;
417✔
21

22
        assert(manager);
417✔
23

24
        log_debug("Serializing...");
417✔
25

26
        Link *link;
417✔
27
        HASHMAP_FOREACH(link, manager->links_by_index) {
2,216✔
28
                _cleanup_(sd_json_variant_unrefp) sd_json_variant *e = NULL;
51✔
29

30
                /* ignore unmanaged, failed, or removed interfaces. */
31
                if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_INITIALIZED, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
1,799✔
32
                        continue;
1,748✔
33

34
                r = sd_json_buildo(
51✔
35
                                &e,
36
                                SD_JSON_BUILD_PAIR_INTEGER("Index", link->ifindex));
37
                if (r < 0)
51✔
38
                        return r;
39

40
                r = addresses_append_json(link, /* serializing = */ true, &e);
51✔
41
                if (r < 0)
51✔
42
                        return r;
43

44
                r = sd_json_variant_append_array(&array, e);
51✔
45
                if (r < 0)
51✔
46
                        return r;
47
        }
48

49
        r = json_variant_set_field_non_null(&v, "Interfaces", array);
417✔
50
        if (r < 0)
417✔
51
                return r;
52

53
        r = nexthops_append_json(manager, /* ifindex = */ -1, &v);
417✔
54
        if (r < 0)
417✔
55
                return r;
56

57
        r = routes_append_json(manager, /* ifindex = */ -1, &v);
417✔
58
        if (r < 0)
417✔
59
                return r;
60

61
        if (!v) {
417✔
62
                log_debug("There is nothing to serialize.");
383✔
63
                return 0;
383✔
64
        }
65

66
        _cleanup_free_ char *dump = NULL;
34✔
67
        r = sd_json_variant_format(v, /* flags = */ 0, &dump);
34✔
68
        if (r < 0)
34✔
69
                return r;
70

71
        _cleanup_close_ int fd = -EBADF;
34✔
72
        fd = memfd_new_and_seal_string("serialization", dump);
34✔
73
        if (fd < 0)
34✔
74
                return fd;
75

76
        r = notify_push_fd(fd, "manager-serialization");
34✔
77
        if (r < 0)
34✔
78
                return log_debug_errno(r, "Failed to push serialization file descriptor: %m");
×
79

80
        log_debug("Serialization completed.");
34✔
81
        return 0;
82
}
83

84
int manager_set_serialization_fd(Manager *manager, int fd, const char *name) {
30✔
85
        assert(manager);
30✔
86
        assert(fd >= 0);
30✔
87
        assert(name);
30✔
88

89
        if (!startswith(name, "manager-serialization"))
30✔
90
                return -EINVAL;
91

92
        if (manager->serialization_fd >= 0)
26✔
93
                return -EEXIST;
94

95
        manager->serialization_fd = fd;
26✔
96
        return 0;
26✔
97
}
98

99
static JSON_DISPATCH_ENUM_DEFINE(json_dispatch_network_config_source, NetworkConfigSource, network_config_source_from_string);
101✔
100

101
static int json_dispatch_address_family(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) {
101✔
102
        int r, *i = ASSERT_PTR(userdata);
101✔
103
        int64_t i64;
101✔
104

105
        assert_return(variant, -EINVAL);
101✔
106

107
        if (FLAGS_SET(flags, SD_JSON_RELAX) && sd_json_variant_is_null(variant)) {
101✔
108
                *i = AF_UNSPEC;
×
109
                return 0;
×
110
        }
111

112
        r = sd_json_dispatch_int64(name, variant, flags, &i64);
101✔
113
        if (r < 0)
101✔
114
                return r;
115

116
        if (!IN_SET(i64, AF_INET, AF_INET6) && !(FLAGS_SET(flags, SD_JSON_RELAX) && i64 == AF_UNSPEC))
101✔
117
                return json_log(variant, flags, SYNTHETIC_ERRNO(ERANGE), "JSON field '%s' out of bounds for an address family.", strna(name));
×
118

119
        *i = (int) i64;
101✔
120
        return 0;
101✔
121
}
122

123
typedef struct AddressParam {
124
        int family;
125
        struct iovec address;
126
        struct iovec peer;
127
        uint8_t prefixlen;
128
        NetworkConfigSource source;
129
        struct iovec provider;
130
} AddressParam;
131

132
static void address_param_done(AddressParam *p) {
68✔
133
        assert(p);
68✔
134

135
        iovec_done(&p->address);
68✔
136
        iovec_done(&p->peer);
68✔
137
        iovec_done(&p->provider);
68✔
138
}
68✔
139

140
static int link_deserialize_address(Link *link, sd_json_variant *v) {
68✔
141
        static const sd_json_dispatch_field dispatch_table[] = {
68✔
142
                { "Family",         _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_address_family,        offsetof(AddressParam, family),    SD_JSON_MANDATORY },
143
                { "Address",        SD_JSON_VARIANT_ARRAY,         json_dispatch_byte_array_iovec,      offsetof(AddressParam, address),   SD_JSON_MANDATORY },
144
                { "Peer",           SD_JSON_VARIANT_ARRAY,         json_dispatch_byte_array_iovec,      offsetof(AddressParam, peer),      0                 },
145
                { "PrefixLength",   _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint8,              offsetof(AddressParam, prefixlen), SD_JSON_MANDATORY },
146
                { "ConfigSource",   SD_JSON_VARIANT_STRING,        json_dispatch_network_config_source, offsetof(AddressParam, source),    SD_JSON_MANDATORY },
147
                { "ConfigProvider", SD_JSON_VARIANT_ARRAY,         json_dispatch_byte_array_iovec,      offsetof(AddressParam, provider),  0                 },
148
                {},
149
        };
150

151
        int r;
68✔
152

153
        assert(link);
68✔
154
        assert(v);
68✔
155

156
        _cleanup_(address_param_done) AddressParam p = {};
68✔
157
        r = sd_json_dispatch(v, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &p);
68✔
158
        if (r < 0)
68✔
159
                return log_link_debug_errno(link, r, "Failed to dispatch address from json variant: %m");
×
160

161
        if (p.address.iov_len != FAMILY_ADDRESS_SIZE(p.family))
68✔
162
                return log_link_debug_errno(link, SYNTHETIC_ERRNO(EINVAL),
×
163
                                            "Dispatched address size (%zu) is incompatible with the family (%s).",
164
                                            p.address.iov_len, af_to_ipv4_ipv6(p.family));
165

166
        if (p.peer.iov_len != 0 && p.peer.iov_len != FAMILY_ADDRESS_SIZE(p.family))
68✔
167
                return log_link_debug_errno(link, SYNTHETIC_ERRNO(EINVAL),
×
168
                                            "Dispatched peer address size (%zu) is incompatible with the family (%s).",
169
                                            p.peer.iov_len, af_to_ipv4_ipv6(p.family));
170

171
        if (p.provider.iov_len != 0 && p.provider.iov_len != FAMILY_ADDRESS_SIZE(p.family))
68✔
172
                return log_link_debug_errno(link, SYNTHETIC_ERRNO(EINVAL),
×
173
                                            "Dispatched provider address size (%zu) is incompatible with the family (%s).",
174
                                            p.provider.iov_len, af_to_ipv4_ipv6(p.family));
175

176
        Address tmp = {
68✔
177
                .family = p.family,
178
                .prefixlen = p.prefixlen,
68✔
179
        };
180

181
        memcpy_safe(&tmp.in_addr, p.address.iov_base, p.address.iov_len);
68✔
182
        memcpy_safe(&tmp.in_addr_peer, p.peer.iov_base, p.peer.iov_len);
68✔
183

184
        Address *address;
68✔
185
        r = address_get(link, &tmp, &address);
68✔
186
        if (r < 0) {
68✔
187
                log_link_debug_errno(link, r, "Cannot find deserialized address %s: %m",
×
188
                                     IN_ADDR_PREFIX_TO_STRING(tmp.family, &tmp.in_addr, tmp.prefixlen));
189
                return 0; /* Already removed? */
×
190
        }
191

192
        if (address->source != NETWORK_CONFIG_SOURCE_FOREIGN)
68✔
193
                return 0; /* Huh?? Already deserialized?? */
194

195
        address->source = p.source;
68✔
196
        memcpy_safe(&address->provider, p.provider.iov_base, p.provider.iov_len);
68✔
197

198
        log_address_debug(address, "Deserialized", link);
68✔
199
        return 0;
200
}
201

202
static int manager_deserialize_link(Manager *manager, sd_json_variant *v) {
37✔
203
        typedef struct LinkParam {
37✔
204
                int ifindex;
205
                sd_json_variant *addresses;
206
        } LinkParam;
207

208
        static const sd_json_dispatch_field dispatch_table[] = {
37✔
209
                { "Index",     _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex,          offsetof(LinkParam, ifindex),   SD_JSON_MANDATORY | SD_JSON_REFUSE_NULL },
210
                { "Addresses", SD_JSON_VARIANT_ARRAY,         sd_json_dispatch_variant_noref, offsetof(LinkParam, addresses), 0                                       },
211
                {},
212
        };
213

214
        int r, ret = 0;
37✔
215

216
        assert(manager);
37✔
217
        assert(v);
37✔
218

219
        LinkParam p = {};
37✔
220
        r = sd_json_dispatch(v, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &p);
37✔
221
        if (r < 0)
37✔
222
                return log_debug_errno(r, "Failed to dispatch interface from json variant: %m");
×
223

224
        Link *link;
37✔
225
        r = link_get_by_index(manager, p.ifindex, &link);
37✔
226
        if (r < 0) {
37✔
227
                log_debug_errno(r, "No interface with deserialized ifindex (%i) found: %m", p.ifindex);
×
228
                return 0; /* Already removed? */
×
229
        }
230

231
        sd_json_variant *i;
37✔
232
        JSON_VARIANT_ARRAY_FOREACH(i, p.addresses)
105✔
233
                RET_GATHER(ret, link_deserialize_address(link, i));
68✔
234

235
        return ret;
37✔
236
}
237

238
typedef struct NextHopParam {
239
        uint32_t id;
240
        int family;
241
        NetworkConfigSource source;
242
        struct iovec provider;
243
} NextHopParam;
244

245
static void nexthop_param_done(NextHopParam *p) {
5✔
246
        assert(p);
5✔
247

248
        iovec_done(&p->provider);
5✔
249
}
5✔
250

251
static int manager_deserialize_nexthop(Manager *manager, sd_json_variant *v) {
5✔
252
        static const sd_json_dispatch_field dispatch_table[] = {
5✔
253
                { "ID",             _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint32,             offsetof(NextHopParam, id),        SD_JSON_MANDATORY },
254
                { "Family",         _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_address_family,        offsetof(NextHopParam, family),    SD_JSON_MANDATORY },
255
                { "ConfigSource",   SD_JSON_VARIANT_STRING,        json_dispatch_network_config_source, offsetof(NextHopParam, source),    SD_JSON_MANDATORY },
256
                { "ConfigProvider", SD_JSON_VARIANT_ARRAY,         json_dispatch_byte_array_iovec,      offsetof(NextHopParam, provider),  0                 },
257
                {},
258
        };
259

260
        int r;
5✔
261

262
        assert(manager);
5✔
263
        assert(v);
5✔
264

265
        _cleanup_(nexthop_param_done) NextHopParam p = {};
5✔
266
        r = sd_json_dispatch(v, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &p);
5✔
267
        if (r < 0)
5✔
268
                return log_debug_errno(r, "Failed to dispatch nexthop from json variant: %m");
×
269

270
        if (p.id == 0)
5✔
271
                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Dispatched nexthop ID is zero.");
×
272

273
        if (p.provider.iov_len != 0 && p.provider.iov_len != FAMILY_ADDRESS_SIZE(p.family))
5✔
274
                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
×
275
                                       "Dispatched provider address size (%zu) is incompatible with the family (%s).",
276
                                       p.provider.iov_len, af_to_ipv4_ipv6(p.family));
277

278
        NextHop *nexthop;
5✔
279
        r = nexthop_get_by_id(manager, p.id, &nexthop);
5✔
280
        if (r < 0) {
5✔
281
                log_debug_errno(r, "Cannot find deserialized nexthop (ID=%"PRIu32"): %m", p.id);
×
282
                return 0; /* Already removed? */
×
283
        }
284

285
        if (nexthop->source != NETWORK_CONFIG_SOURCE_FOREIGN)
5✔
286
                return 0; /* Huh?? Already deserialized?? */
287

288
        nexthop->source = p.source;
5✔
289
        memcpy_safe(&nexthop->provider, p.provider.iov_base, p.provider.iov_len);
5✔
290

291
        log_nexthop_debug(nexthop, "Deserialized", manager);
5✔
292
        return 0;
293
}
294

295
typedef struct RouteParam {
296
        Route route;
297

298
        struct iovec dst;
299
        struct iovec src;
300
        struct iovec prefsrc;
301
        struct iovec gw;
302
        struct iovec metrics;
303
        struct iovec provider;
304
} RouteParam;
305

306
static void route_param_done(RouteParam *p) {
28✔
307
        assert(p);
28✔
308

309
        free(p->route.metric.metrics);
28✔
310

311
        iovec_done(&p->dst);
28✔
312
        iovec_done(&p->src);
28✔
313
        iovec_done(&p->prefsrc);
28✔
314
        iovec_done(&p->gw);
28✔
315
        iovec_done(&p->metrics);
28✔
316
        iovec_done(&p->provider);
28✔
317
}
28✔
318

319
static int manager_deserialize_route(Manager *manager, sd_json_variant *v) {
28✔
320
        static const sd_json_dispatch_field dispatch_table[] = {
28✔
321
                /* rtmsg header */
322
                { "Family",                        _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_address_family,        offsetof(RouteParam, route.family),                             SD_JSON_MANDATORY                 },
323
                { "DestinationPrefixLength",       _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint8,              offsetof(RouteParam, route.dst_prefixlen),                      SD_JSON_MANDATORY                 },
324
                { "SourcePrefixLength",            _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint8,              offsetof(RouteParam, route.src_prefixlen),                      0                                 },
325
                { "TOS",                           _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint8,              offsetof(RouteParam, route.tos),                                SD_JSON_MANDATORY                 },
326
                { "Protocol",                      _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint8,              offsetof(RouteParam, route.protocol),                           SD_JSON_MANDATORY                 },
327
                { "Scope",                         _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint8,              offsetof(RouteParam, route.scope),                              SD_JSON_MANDATORY                 },
328
                { "Type",                          _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint8,              offsetof(RouteParam, route.type),                               SD_JSON_MANDATORY                 },
329
                { "Flags",                         _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint32,             offsetof(RouteParam, route.flags),                              SD_JSON_MANDATORY                 },
330
                /* attributes */
331
                { "Destination",                   SD_JSON_VARIANT_ARRAY,         json_dispatch_byte_array_iovec,      offsetof(RouteParam, dst),                                      SD_JSON_MANDATORY                 },
332
                { "Source",                        SD_JSON_VARIANT_ARRAY,         json_dispatch_byte_array_iovec,      offsetof(RouteParam, src),                                      0                                 },
333
                { "Priority",                      _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint32,             offsetof(RouteParam, route.priority),                           SD_JSON_MANDATORY                 },
334
                { "PreferredSource",               SD_JSON_VARIANT_ARRAY,         json_dispatch_byte_array_iovec,      offsetof(RouteParam, prefsrc),                                  0                                 },
335
                { "Table",                         _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint32,             offsetof(RouteParam, route.table),                              SD_JSON_MANDATORY                 },
336
                /* nexthops */
337
                { "Gateway",                       SD_JSON_VARIANT_ARRAY,         json_dispatch_byte_array_iovec,      offsetof(RouteParam, gw),                                       0                                 },
338
                { "InterfaceIndex",                _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex,               offsetof(RouteParam, route.nexthop.ifindex),                    SD_JSON_MANDATORY | SD_JSON_RELAX },
339
                { "NextHopID",                     _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint32,             offsetof(RouteParam, route.nexthop_id),                         0                                 },
340
                /* metrics */
341
                { "Metrics",                       SD_JSON_VARIANT_ARRAY,         json_dispatch_byte_array_iovec,      offsetof(RouteParam, metrics),                                  0                                 },
342
                { "TCPCongestionControlAlgorithm", SD_JSON_VARIANT_STRING,        sd_json_dispatch_const_string,       offsetof(RouteParam, route.metric.tcp_congestion_control_algo), 0                                 },
343
                /* config */
344
                { "ConfigSource",                  SD_JSON_VARIANT_STRING,        json_dispatch_network_config_source, offsetof(RouteParam, route.source),                             SD_JSON_MANDATORY                 },
345
                { "ConfigProvider",                SD_JSON_VARIANT_ARRAY,         json_dispatch_byte_array_iovec,      offsetof(RouteParam, provider),                                 0                                 },
346
                {},
347
        };
348

349
        int r;
28✔
350

351
        assert(manager);
28✔
352
        assert(v);
28✔
353

354
        _cleanup_(route_param_done) RouteParam p = {};
28✔
355
        r = sd_json_dispatch(v, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &p);
28✔
356
        if (r < 0)
28✔
357
                return log_debug_errno(r, "Failed to dispatch route from json variant: %m");
×
358

359
        if (p.dst.iov_len != FAMILY_ADDRESS_SIZE(p.route.family))
28✔
360
                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
×
361
                                       "Dispatched destination address size (%zu) is incompatible with the family (%s).",
362
                                       p.dst.iov_len, af_to_ipv4_ipv6(p.route.family));
363

364
        if (p.src.iov_len != 0 && p.src.iov_len != FAMILY_ADDRESS_SIZE(p.route.family))
28✔
365
                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
×
366
                                       "Dispatched source address size (%zu) is incompatible with the family (%s).",
367
                                       p.src.iov_len, af_to_ipv4_ipv6(p.route.family));
368

369
        if (p.prefsrc.iov_len != 0 && p.prefsrc.iov_len != FAMILY_ADDRESS_SIZE(p.route.family))
28✔
370
                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
×
371
                                       "Dispatched preferred source address size (%zu) is incompatible with the family (%s).",
372
                                       p.prefsrc.iov_len, af_to_ipv4_ipv6(p.route.family));
373

374
        switch (p.gw.iov_len) {
28✔
375
        case 0:
20✔
376
                p.route.nexthop.family = AF_UNSPEC;
20✔
377
                break;
20✔
378
        case sizeof(struct in_addr):
7✔
379
                p.route.nexthop.family = AF_INET;
7✔
380
                break;
7✔
381
        case sizeof(struct in6_addr):
1✔
382
                p.route.nexthop.family = AF_INET6;
1✔
383
                break;
1✔
384
        default:
UNCOV
385
                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
×
386
                                       "Dispatched gateway address size (%zu) is invalid.",
387
                                       p.prefsrc.iov_len);
388
        }
389

390
        if (p.metrics.iov_len % sizeof(uint32_t) != 0)
28✔
391
                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
×
392
                                       "Dispatched route metric size (%zu) is invalid.",
393
                                       p.metrics.iov_len);
394

395
        if (p.provider.iov_len != 0 && p.provider.iov_len != FAMILY_ADDRESS_SIZE(p.route.family))
28✔
396
                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
×
397
                                       "Dispatched provider address size (%zu) is incompatible with the family (%s).",
398
                                       p.provider.iov_len, af_to_ipv4_ipv6(p.route.family));
399

400
        memcpy_safe(&p.route.dst, p.dst.iov_base, p.dst.iov_len);
28✔
401
        memcpy_safe(&p.route.src, p.src.iov_base, p.src.iov_len);
28✔
402
        memcpy_safe(&p.route.prefsrc, p.prefsrc.iov_base, p.prefsrc.iov_len);
28✔
403
        memcpy_safe(&p.route.nexthop.gw, p.gw.iov_base, p.gw.iov_len);
28✔
404

405
        p.route.metric.n_metrics = p.metrics.iov_len / sizeof(uint32_t);
28✔
406
        p.route.metric.metrics = new(uint32_t, p.route.metric.n_metrics);
28✔
407
        if (!p.route.metric.metrics)
28✔
408
                return log_oom_debug();
×
409

410
        memcpy_safe(p.route.metric.metrics, p.metrics.iov_base, p.metrics.iov_len);
28✔
411

412
        Route *route;
28✔
413
        r = route_get(manager, &p.route, &route);
28✔
414
        if (r < 0) {
28✔
415
                log_route_debug(&p.route, "Cannot find deserialized", manager);
×
416
                return 0; /* Already removed? */
417
        }
418

419
        if (route->source != NETWORK_CONFIG_SOURCE_FOREIGN)
28✔
420
                return 0; /* Huh?? Already deserialized?? */
421

422
        route->source = p.route.source;
28✔
423
        memcpy_safe(&route->provider, p.provider.iov_base, p.provider.iov_len);
28✔
424

425
        log_route_debug(route, "Deserialized", manager);
28✔
426
        return 0;
427
}
428

429
int manager_deserialize(Manager *manager) {
417✔
430
        int r, ret = 0;
417✔
431

432
        assert(manager);
417✔
433

434
        _cleanup_close_ int fd = TAKE_FD(manager->serialization_fd);
417✔
435
        if (fd < 0)
417✔
436
                return 0;
437

438
        log_debug("Deserializing...");
26✔
439

440
        _cleanup_fclose_ FILE *f = take_fdopen(&fd, "r");
443✔
441
        if (!f)
26✔
442
                return log_debug_errno(errno, "Failed to fdopen() serialization file descriptor: %m");
×
443

444
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
26✔
445
        unsigned err_line = 0, err_column = 0;
26✔
446
        r = sd_json_parse_file(
26✔
447
                        f,
448
                        /* path = */ NULL,
449
                        /* flags = */ 0,
450
                        &v,
451
                        &err_line,
452
                        &err_column);
453
        if (r < 0)
26✔
454
                return log_debug_errno(r, "Failed to parse json (line=%u, column=%u): %m", err_line, err_column);
1✔
455

456
        sd_json_variant *i;
25✔
457
        JSON_VARIANT_ARRAY_FOREACH(i, sd_json_variant_by_key(v, "Interfaces"))
62✔
458
                RET_GATHER(ret, manager_deserialize_link(manager, i));
37✔
459

460
        JSON_VARIANT_ARRAY_FOREACH(i, sd_json_variant_by_key(v, "NextHops"))
30✔
461
                RET_GATHER(ret, manager_deserialize_nexthop(manager, i));
5✔
462

463
        JSON_VARIANT_ARRAY_FOREACH(i, sd_json_variant_by_key(v, "Routes"))
53✔
464
                RET_GATHER(ret, manager_deserialize_route(manager, i));
28✔
465

466
        log_debug("Deserialization completed.");
25✔
467
        return ret;
468
}
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