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

systemd / systemd / 16458254342

22 Jul 2025 11:49PM UTC coverage: 72.173% (+0.05%) from 72.121%
16458254342

push

github

yuwata
meson: prepend sys_root to bpf isystem

These sort of absolute include paths are generally unsafe when cross compiling.

302515 of 419153 relevant lines covered (72.17%)

734662.87 hits per line

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

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

3
#include <linux/nexthop.h>
4

5
#include "sd-device.h"
6
#include "sd-dhcp-client.h"
7
#include "sd-dhcp6-client.h"
8

9
#include "dhcp-lease-internal.h"
10
#include "dhcp-server-lease-internal.h"
11
#include "dhcp6-lease-internal.h"
12
#include "extract-word.h"
13
#include "ip-protocol-list.h"
14
#include "json-util.h"
15
#include "netif-util.h"
16
#include "networkd-address.h"
17
#include "networkd-dhcp-common.h"
18
#include "networkd-json.h"
19
#include "networkd-link.h"
20
#include "networkd-manager.h"
21
#include "networkd-neighbor.h"
22
#include "networkd-network.h"
23
#include "networkd-nexthop.h"
24
#include "networkd-ntp.h"
25
#include "networkd-route.h"
26
#include "networkd-route-util.h"
27
#include "networkd-routing-policy-rule.h"
28
#include "ordered-set.h"
29
#include "set.h"
30
#include "string-util.h"
31
#include "strv.h"
32
#include "udev-util.h"
33
#include "wifi-util.h"
34

35
static int address_append_json(Address *address, bool serializing, sd_json_variant **array) {
897✔
36
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
897✔
37
        int r;
897✔
38

39
        assert(address);
897✔
40
        assert(array);
897✔
41

42
        r = sd_json_buildo(
897✔
43
                        &v,
44
                        SD_JSON_BUILD_PAIR_INTEGER("Family", address->family),
45
                        JSON_BUILD_PAIR_IN_ADDR("Address", &address->in_addr, address->family),
46
                        JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Peer", &address->in_addr_peer, address->family),
47
                        SD_JSON_BUILD_PAIR_UNSIGNED("PrefixLength", address->prefixlen),
48
                        SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(address->source)),
49
                        JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", &address->provider, address->family));
50
        if (r < 0)
897✔
51
                return r;
52

53
        if (!serializing) {
897✔
54
                _cleanup_free_ char *scope = NULL, *flags = NULL, *state = NULL;
804✔
55

56
                r = route_scope_to_string_alloc(address->scope, &scope);
804✔
57
                if (r < 0)
804✔
58
                        return r;
59

60
                r = address_flags_to_string_alloc(address->flags, address->family, &flags);
804✔
61
                if (r < 0)
804✔
62
                        return r;
63

64
                r = network_config_state_to_string_alloc(address->state, &state);
804✔
65
                if (r < 0)
804✔
66
                        return r;
67

68
                r = sd_json_variant_merge_objectbo(
804✔
69
                                &v,
70
                                JSON_BUILD_PAIR_IN4_ADDR_NON_NULL("Broadcast", &address->broadcast),
71
                                SD_JSON_BUILD_PAIR_UNSIGNED("Scope", address->scope),
72
                                SD_JSON_BUILD_PAIR_STRING("ScopeString", scope),
73
                                SD_JSON_BUILD_PAIR_UNSIGNED("Flags", address->flags),
74
                                SD_JSON_BUILD_PAIR_STRING("FlagsString", flags),
75
                                JSON_BUILD_PAIR_STRING_NON_EMPTY("Label", address->label),
76
                                JSON_BUILD_PAIR_FINITE_USEC("PreferredLifetimeUSec", address->lifetime_preferred_usec),
77
                                JSON_BUILD_PAIR_FINITE_USEC("PreferredLifetimeUsec", address->lifetime_preferred_usec), /* for backward compat */
78
                                JSON_BUILD_PAIR_FINITE_USEC("ValidLifetimeUSec", address->lifetime_valid_usec),
79
                                JSON_BUILD_PAIR_FINITE_USEC("ValidLifetimeUsec", address->lifetime_valid_usec), /* for backward compat */
80
                                SD_JSON_BUILD_PAIR_STRING("ConfigState", state));
81
                if (r < 0)
804✔
82
                        return r;
83
        }
84

85
        return sd_json_variant_append_array(array, v);
897✔
86
}
87

88
int addresses_append_json(Link *link, bool serializing, sd_json_variant **v) {
637✔
89
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
637✔
90
        Address *address;
637✔
91
        int r;
637✔
92

93
        assert(link);
637✔
94
        assert(v);
637✔
95

96
        SET_FOREACH(address, link->addresses) {
1,590✔
97
                if (serializing) {
953✔
98
                        if (address->source == NETWORK_CONFIG_SOURCE_FOREIGN)
149✔
99
                                continue;
56✔
100
                        if (!address_is_ready(address))
93✔
101
                                continue;
×
102

103
                        log_address_debug(address, "Serializing", link);
93✔
104
                }
105

106
                r = address_append_json(address, serializing, &array);
897✔
107
                if (r < 0)
897✔
108
                        return r;
×
109
        }
110

111
        return json_variant_set_field_non_null(v, "Addresses", array);
637✔
112
}
113

114
static int neighbor_append_json(Neighbor *n, sd_json_variant **array) {
8✔
115
        _cleanup_free_ char *state = NULL;
8✔
116
        int r;
8✔
117

118
        assert(n);
8✔
119
        assert(array);
8✔
120

121
        r = network_config_state_to_string_alloc(n->state, &state);
8✔
122
        if (r < 0)
8✔
123
                return r;
124

125
        return sd_json_variant_append_arraybo(
8✔
126
                        array,
127
                        SD_JSON_BUILD_PAIR_INTEGER("Family", n->dst_addr.family),
128
                        JSON_BUILD_PAIR_IN_ADDR("Destination", &n->dst_addr.address, n->dst_addr.family),
129
                        JSON_BUILD_PAIR_HW_ADDR("LinkLayerAddress", &n->ll_addr),
130
                        SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(n->source)),
131
                        SD_JSON_BUILD_PAIR_STRING("ConfigState", state));
132
}
133

134
static int neighbors_append_json(Set *neighbors, sd_json_variant **v) {
580✔
135
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
580✔
136
        Neighbor *neighbor;
580✔
137
        int r;
580✔
138

139
        assert(v);
580✔
140

141
        SET_FOREACH(neighbor, neighbors) {
588✔
142
                r = neighbor_append_json(neighbor, &array);
8✔
143
                if (r < 0)
8✔
144
                        return r;
×
145
        }
146

147
        return json_variant_set_field_non_null(v, "Neighbors", array);
580✔
148
}
149

150
static int nexthop_group_build_json(NextHop *nexthop, sd_json_variant **ret) {
113✔
151
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
113✔
152
        struct nexthop_grp *g;
113✔
153
        int r;
113✔
154

155
        assert(nexthop);
113✔
156
        assert(ret);
113✔
157

158
        HASHMAP_FOREACH(g, nexthop->group) {
125✔
159
                r = sd_json_variant_append_arraybo(
12✔
160
                                &array,
161
                                SD_JSON_BUILD_PAIR_UNSIGNED("ID", g->id),
162
                                SD_JSON_BUILD_PAIR_UNSIGNED("Weight", g->weight+1));
163
                if (r < 0)
12✔
164
                        return r;
×
165
        }
166

167
        *ret = TAKE_PTR(array);
113✔
168
        return 0;
113✔
169
}
170

171
static int nexthop_append_json(NextHop *n, bool serializing, sd_json_variant **array) {
118✔
172
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
118✔
173
        int r;
118✔
174

175
        assert(n);
118✔
176
        assert(array);
118✔
177

178
        r = sd_json_buildo(
118✔
179
                        &v,
180
                        SD_JSON_BUILD_PAIR_UNSIGNED("ID", n->id),
181
                        SD_JSON_BUILD_PAIR_INTEGER("Family", n->family),
182
                        SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(n->source)),
183
                        JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", &n->provider, n->family));
184
        if (r < 0)
118✔
185
                return r;
186

187
        if (!serializing) {
118✔
188
                _cleanup_(sd_json_variant_unrefp) sd_json_variant *group = NULL;
113✔
189
                _cleanup_free_ char *flags = NULL, *protocol = NULL, *state = NULL;
113✔
190

191
                r = route_flags_to_string_alloc(n->flags, &flags);
113✔
192
                if (r < 0)
113✔
193
                        return r;
194

195
                r = route_protocol_to_string_alloc(n->protocol, &protocol);
113✔
196
                if (r < 0)
113✔
197
                        return r;
198

199
                r = network_config_state_to_string_alloc(n->state, &state);
113✔
200
                if (r < 0)
113✔
201
                        return r;
202

203
                r = nexthop_group_build_json(n, &group);
113✔
204
                if (r < 0)
113✔
205
                        return r;
206

207
                r = sd_json_variant_merge_objectbo(
220✔
208
                                &v,
209
                                JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Gateway", &n->gw.address, n->family),
210
                                SD_JSON_BUILD_PAIR_UNSIGNED("Flags", n->flags),
211
                                SD_JSON_BUILD_PAIR_STRING("FlagsString", strempty(flags)),
212
                                SD_JSON_BUILD_PAIR_UNSIGNED("Protocol", n->protocol),
213
                                SD_JSON_BUILD_PAIR_STRING("ProtocolString", protocol),
214
                                SD_JSON_BUILD_PAIR_BOOLEAN("Blackhole", n->blackhole),
215
                                JSON_BUILD_PAIR_VARIANT_NON_NULL("Group", group),
216
                                SD_JSON_BUILD_PAIR_STRING("ConfigState", state));
217
        }
218

219
        return sd_json_variant_append_array(array, v);
118✔
220
}
221

222
int nexthops_append_json(Manager *manager, int ifindex, sd_json_variant **v) {
1,096✔
223
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
1,096✔
224
        NextHop *nexthop;
1,096✔
225
        int r;
1,096✔
226

227
        assert(manager);
1,096✔
228
        assert(v);
1,096✔
229

230
        HASHMAP_FOREACH(nexthop, manager->nexthops_by_id) {
2,206✔
231
                if (ifindex >= 0) {
1,110✔
232
                        if (nexthop->ifindex != ifindex)
1,105✔
233
                                continue;
992✔
234
                } else {
235
                        /* negative ifindex means we are serializing now. */
236

237
                        if (nexthop->source == NETWORK_CONFIG_SOURCE_FOREIGN)
5✔
238
                                continue;
×
239
                        if (!nexthop_exists(nexthop))
5✔
240
                                continue;
×
241

242
                        log_nexthop_debug(nexthop, "Serializing", manager);
5✔
243
                }
244

245
                r = nexthop_append_json(nexthop, /* serializing = */ ifindex < 0, &array);
118✔
246
                if (r < 0)
118✔
247
                        return r;
×
248
        }
249

250
        return json_variant_set_field_non_null(v, "NextHops", array);
1,096✔
251
}
252

253
static int route_append_json(Route *route, bool serializing, sd_json_variant **array) {
2,290✔
254
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
2,290✔
255
        int r;
2,290✔
256

257
        assert(route);
2,290✔
258
        assert(array);
2,290✔
259

260
        r = sd_json_buildo(
2,290✔
261
                        &v,
262
                        SD_JSON_BUILD_PAIR_INTEGER("Family", route->family),
263
                        JSON_BUILD_PAIR_IN_ADDR("Destination", &route->dst, route->family),
264
                        SD_JSON_BUILD_PAIR_UNSIGNED("DestinationPrefixLength", route->dst_prefixlen),
265
                        JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Gateway", &route->nexthop.gw, route->nexthop.family),
266
                        SD_JSON_BUILD_PAIR_CONDITION(route->src_prefixlen > 0,
267
                                                     "Source", JSON_BUILD_IN_ADDR(&route->src, route->family)),
268
                        JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("SourcePrefixLength", route->src_prefixlen),
269
                        JSON_BUILD_PAIR_IN_ADDR_NON_NULL("PreferredSource", &route->prefsrc, route->family),
270
                        SD_JSON_BUILD_PAIR_UNSIGNED("TOS", route->tos),
271
                        SD_JSON_BUILD_PAIR_UNSIGNED("Scope", route->scope),
272
                        SD_JSON_BUILD_PAIR_UNSIGNED("Protocol", route->protocol),
273
                        SD_JSON_BUILD_PAIR_UNSIGNED("Type", route->type),
274
                        SD_JSON_BUILD_PAIR_UNSIGNED("Priority", route->priority),
275
                        SD_JSON_BUILD_PAIR_UNSIGNED("Table", route->table),
276
                        SD_JSON_BUILD_PAIR_UNSIGNED("Flags", route->flags),
277
                        JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("NextHopID", route->nexthop_id),
278
                        SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(route->source)),
279
                        JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", &route->provider, route->family));
280
        if (r < 0)
2,290✔
281
                return r;
282

283
        if (serializing) {
2,290✔
284
                r = sd_json_variant_merge_objectbo(
41✔
285
                                &v,
286
                                SD_JSON_BUILD_PAIR_INTEGER("InterfaceIndex", route->nexthop.ifindex),
287
                                JSON_BUILD_PAIR_BYTE_ARRAY_NON_EMPTY("Metrics", route->metric.metrics, route->metric.n_metrics),
288
                                JSON_BUILD_PAIR_STRING_NON_EMPTY("TCPCongestionControlAlgorithm", route->metric.tcp_congestion_control_algo));
289
                if (r < 0)
41✔
290
                        return r;
291
        } else {
292
                _cleanup_free_ char *scope = NULL, *protocol = NULL, *table = NULL, *flags = NULL, *state = NULL;
2,249✔
293

294
                r = route_scope_to_string_alloc(route->scope, &scope);
2,249✔
295
                if (r < 0)
2,249✔
296
                        return r;
297

298
                r = route_protocol_to_string_alloc(route->protocol, &protocol);
2,249✔
299
                if (r < 0)
2,249✔
300
                        return r;
301

302
                r = manager_get_route_table_to_string(route->manager, route->table, /* append_num = */ false, &table);
2,249✔
303
                if (r < 0)
2,249✔
304
                        return r;
305

306
                r = route_flags_to_string_alloc(route->flags, &flags);
2,249✔
307
                if (r < 0)
2,249✔
308
                        return r;
309

310
                r = network_config_state_to_string_alloc(route->state, &state);
2,249✔
311
                if (r < 0)
2,249✔
312
                        return r;
313

314
                r = sd_json_variant_merge_objectbo(
4,482✔
315
                                &v,
316
                                SD_JSON_BUILD_PAIR_STRING("ScopeString", scope),
317
                                SD_JSON_BUILD_PAIR_STRING("ProtocolString", protocol),
318
                                SD_JSON_BUILD_PAIR_STRING("TypeString", route_type_to_string(route->type)),
319
                                SD_JSON_BUILD_PAIR_STRING("TableString", table),
320
                                JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("MTU", route_metric_get(&route->metric, RTAX_MTU)),
321
                                SD_JSON_BUILD_PAIR_UNSIGNED("Preference", route->pref),
322
                                SD_JSON_BUILD_PAIR_STRING("FlagsString", strempty(flags)),
323
                                JSON_BUILD_PAIR_FINITE_USEC("LifetimeUSec", route->lifetime_usec),
324
                                SD_JSON_BUILD_PAIR_STRING("ConfigState", state));
325
                if (r < 0)
2,249✔
326
                        return r;
327
        }
328

329
        return sd_json_variant_append_array(array, v);
2,290✔
330
}
331

332
int routes_append_json(Manager *manager, int ifindex, sd_json_variant **v) {
1,096✔
333
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
1,096✔
334
        Route *route;
1,096✔
335
        int r;
1,096✔
336

337
        assert(manager);
1,096✔
338
        assert(v);
1,096✔
339

340
        SET_FOREACH(route, manager->routes) {
21,856✔
341
                if (ifindex >= 0) {
20,760✔
342
                        if (route->nexthop.ifindex != ifindex)
18,541✔
343
                                continue;
16,292✔
344
                } else {
345
                        /* negative ifindex means we are serializing now. */
346

347
                        if (route->source == NETWORK_CONFIG_SOURCE_FOREIGN)
2,219✔
348
                                continue;
2,178✔
349
                        if (!route_exists(route))
41✔
350
                                continue;
×
351

352
                        log_route_debug(route, "Serializing", manager);
41✔
353
                }
354

355
                r = route_append_json(route, /* serializing = */ ifindex < 0, &array);
2,290✔
356
                if (r < 0)
2,290✔
357
                        return r;
×
358
        }
359

360
        return json_variant_set_field_non_null(v, "Routes", array);
1,096✔
361
}
362

363
static int routing_policy_rule_append_json(RoutingPolicyRule *rule, sd_json_variant **array) {
413✔
364
        _cleanup_free_ char *table = NULL, *protocol = NULL, *state = NULL;
413✔
365
        int r;
413✔
366

367
        assert(rule);
413✔
368
        assert(rule->manager);
413✔
369
        assert(array);
413✔
370

371
        r = manager_get_route_table_to_string(rule->manager, rule->table, /* append_num = */ false, &table);
413✔
372
        if (r < 0 && r != -EINVAL)
413✔
373
                return r;
374

375
        r = route_protocol_to_string_alloc(rule->protocol, &protocol);
413✔
376
        if (r < 0)
413✔
377
                return r;
378

379
        r = network_config_state_to_string_alloc(rule->state, &state);
413✔
380
        if (r < 0)
413✔
381
                return r;
382

383
        return sd_json_variant_append_arraybo(
1,652✔
384
                        array,
385
                        SD_JSON_BUILD_PAIR_INTEGER("Family", rule->family),
386
                        JSON_BUILD_PAIR_IN_ADDR_NON_NULL("FromPrefix", &rule->from.address, rule->family),
387
                        SD_JSON_BUILD_PAIR_CONDITION(in_addr_is_set(rule->family, &rule->from.address),
388
                                                     "FromPrefixLength", SD_JSON_BUILD_UNSIGNED(rule->from.prefixlen)),
389
                        JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ToPrefix", &rule->to.address, rule->family),
390
                        SD_JSON_BUILD_PAIR_CONDITION(in_addr_is_set(rule->family, &rule->to.address),
391
                                                     "ToPrefixLength", SD_JSON_BUILD_UNSIGNED(rule->to.prefixlen)),
392
                        SD_JSON_BUILD_PAIR_UNSIGNED("Protocol", rule->protocol),
393
                        SD_JSON_BUILD_PAIR_STRING("ProtocolString", protocol),
394
                        SD_JSON_BUILD_PAIR_UNSIGNED("TOS", rule->tos),
395
                        SD_JSON_BUILD_PAIR_UNSIGNED("Type", rule->action),
396
                        SD_JSON_BUILD_PAIR_STRING("TypeString", fr_act_type_to_string(rule->action)),
397
                        SD_JSON_BUILD_PAIR_UNSIGNED("IPProtocol", rule->ipproto),
398
                        SD_JSON_BUILD_PAIR_STRING("IPProtocolString", ip_protocol_to_name(rule->ipproto)),
399
                        SD_JSON_BUILD_PAIR_UNSIGNED("Priority", rule->priority),
400
                        SD_JSON_BUILD_PAIR_UNSIGNED("FirewallMark", rule->fwmark),
401
                        SD_JSON_BUILD_PAIR_UNSIGNED("FirewallMask", rule->fwmask),
402
                        JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("Table", rule->table),
403
                        JSON_BUILD_PAIR_STRING_NON_EMPTY("TableString", table),
404
                        SD_JSON_BUILD_PAIR_BOOLEAN("Invert", FLAGS_SET(rule->flags, FIB_RULE_INVERT)),
405
                        SD_JSON_BUILD_PAIR_CONDITION(rule->suppress_prefixlen >= 0,
406
                                                     "SuppressPrefixLength", SD_JSON_BUILD_UNSIGNED(rule->suppress_prefixlen)),
407
                        SD_JSON_BUILD_PAIR_CONDITION(rule->suppress_ifgroup >= 0,
408
                                                     "SuppressInterfaceGroup", SD_JSON_BUILD_UNSIGNED(rule->suppress_ifgroup)),
409
                        SD_JSON_BUILD_PAIR_CONDITION(rule->sport.start != 0 || rule->sport.end != 0, "SourcePort",
410
                                                     SD_JSON_BUILD_ARRAY(SD_JSON_BUILD_UNSIGNED(rule->sport.start), SD_JSON_BUILD_UNSIGNED(rule->sport.end))),
411
                        SD_JSON_BUILD_PAIR_CONDITION(rule->dport.start != 0 || rule->dport.end != 0, "DestinationPort",
412
                                                     SD_JSON_BUILD_ARRAY(SD_JSON_BUILD_UNSIGNED(rule->dport.start), SD_JSON_BUILD_UNSIGNED(rule->dport.end))),
413
                        SD_JSON_BUILD_PAIR_CONDITION(rule->uid_range.start != UID_INVALID && rule->uid_range.end != UID_INVALID, "User",
414
                                                     SD_JSON_BUILD_ARRAY(SD_JSON_BUILD_UNSIGNED(rule->uid_range.start), SD_JSON_BUILD_UNSIGNED(rule->uid_range.end))),
415
                        JSON_BUILD_PAIR_STRING_NON_EMPTY("IncomingInterface", rule->iif),
416
                        JSON_BUILD_PAIR_STRING_NON_EMPTY("OutgoingInterface", rule->oif),
417
                        SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(rule->source)),
418
                        SD_JSON_BUILD_PAIR_STRING("ConfigState", state));
419
}
420

421
static int routing_policy_rules_append_json(Set *rules, sd_json_variant **v) {
78✔
422
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
78✔
423
        RoutingPolicyRule *rule;
78✔
424
        int r;
78✔
425

426
        assert(v);
78✔
427

428
        SET_FOREACH(rule, rules) {
491✔
429
                r = routing_policy_rule_append_json(rule, &array);
413✔
430
                if (r < 0)
413✔
431
                        return r;
×
432
        }
433

434
        return json_variant_set_field_non_null(v, "RoutingPolicyRules", array);
78✔
435
}
436

437
static int network_append_json(Network *network, sd_json_variant **v) {
580✔
438
        assert(v);
580✔
439

440
        if (!network)
580✔
441
                return 0;
442

443
        return sd_json_variant_merge_objectbo(
163✔
444
                        v,
445
                        SD_JSON_BUILD_PAIR_STRING("NetworkFile", network->filename),
446
                        SD_JSON_BUILD_PAIR_STRV("NetworkFileDropins", network->dropins),
447
                        SD_JSON_BUILD_PAIR_BOOLEAN("RequiredForOnline", network->required_for_online),
448
                        SD_JSON_BUILD_PAIR("RequiredOperationalStateForOnline",
449
                                           SD_JSON_BUILD_ARRAY(SD_JSON_BUILD_STRING(link_operstate_to_string(network->required_operstate_for_online.min)),
450
                                                               SD_JSON_BUILD_STRING(link_operstate_to_string(network->required_operstate_for_online.max)))),
451
                        SD_JSON_BUILD_PAIR_STRING("RequiredFamilyForOnline",
452
                                                  link_required_address_family_to_string(network->required_family_for_online)),
453
                        SD_JSON_BUILD_PAIR_STRING("ActivationPolicy",
454
                                                  activation_policy_to_string(network->activation_policy)));
455
}
456

457
static int netdev_append_json(NetDev *netdev, sd_json_variant **v) {
580✔
458
        assert(v);
580✔
459

460
        if (!netdev)
580✔
461
                return 0;
462

463
        return sd_json_variant_merge_objectbo(
165✔
464
                        v,
465
                        SD_JSON_BUILD_PAIR_STRING("NetDevFile", netdev->filename),
466
                        SD_JSON_BUILD_PAIR_STRV("NetDevFileDropins", netdev->dropins));
467
}
468

469
static int device_append_json(sd_device *device, sd_json_variant **v) {
580✔
470
        _cleanup_strv_free_ char **link_dropins = NULL;
580✔
471
        const char *link = NULL, *path = NULL, *vendor = NULL, *model = NULL, *joined;
580✔
472
        int r;
580✔
473

474
        assert(v);
580✔
475

476
        if (!device)
580✔
477
                return 0;
478

479
        (void) sd_device_get_property_value(device, "ID_NET_LINK_FILE", &link);
580✔
480

481
        if (sd_device_get_property_value(device, "ID_NET_LINK_FILE_DROPINS", &joined) >= 0) {
580✔
482
                 r = strv_split_full(&link_dropins, joined, ":", EXTRACT_CUNESCAPE);
×
483
                 if (r < 0)
×
484
                        return r;
485
        }
486

487
        (void) sd_device_get_property_value(device, "ID_PATH", &path);
580✔
488

489
        (void) device_get_vendor_string(device, &vendor);
580✔
490
        (void) device_get_model_string(device, &model);
580✔
491

492
        return sd_json_variant_merge_objectbo(
580✔
493
                        v,
494
                        JSON_BUILD_PAIR_STRING_NON_EMPTY("LinkFile", link),
495
                        JSON_BUILD_PAIR_STRV_NON_EMPTY("LinkFileDropins", link_dropins),
496
                        JSON_BUILD_PAIR_STRING_NON_EMPTY("Path", path),
497
                        JSON_BUILD_PAIR_STRING_NON_EMPTY("Vendor", vendor),
498
                        JSON_BUILD_PAIR_STRING_NON_EMPTY("Model", model));
499
}
500

501
static int dns_append_json_one(Link *link, const struct in_addr_full *a, NetworkConfigSource s, const union in_addr_union *p, sd_json_variant **array) {
65✔
502
        assert(link);
65✔
503
        assert(a);
65✔
504
        assert(array);
65✔
505

506
        if (a->ifindex != 0 && a->ifindex != link->ifindex)
65✔
507
                return 0;
508

509
        return sd_json_variant_append_arraybo(
65✔
510
                        array,
511
                        SD_JSON_BUILD_PAIR_INTEGER("Family", a->family),
512
                        JSON_BUILD_PAIR_IN_ADDR("Address", &a->address, a->family),
513
                        JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("Port", a->port),
514
                        SD_JSON_BUILD_PAIR_CONDITION(a->ifindex != 0, "InterfaceIndex", SD_JSON_BUILD_INTEGER(a->ifindex)),
515
                        JSON_BUILD_PAIR_STRING_NON_EMPTY("ServerName", a->server_name),
516
                        SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)),
517
                        JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", p, a->family));
518
}
519

520
static int dns_append_json(Link *link, sd_json_variant **v) {
580✔
521
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
580✔
522
        int r;
580✔
523

524
        assert(link);
580✔
525
        assert(v);
580✔
526

527
        if (!link->network)
580✔
528
                return 0;
529

530
        if (link->n_dns != UINT_MAX)
163✔
531
                for (unsigned i = 0; i < link->n_dns; i++) {
8✔
532
                        r = dns_append_json_one(link, link->dns[i], NETWORK_CONFIG_SOURCE_RUNTIME, NULL, &array);
6✔
533
                        if (r < 0)
6✔
534
                                return r;
535
                }
536
        else {
537
                for (unsigned i = 0; i < link->network->n_dns; i++) {
169✔
538
                        r = dns_append_json_one(link, link->network->dns[i], NETWORK_CONFIG_SOURCE_STATIC, NULL, &array);
8✔
539
                        if (r < 0)
8✔
540
                                return r;
541
                }
542

543
                if (link->dhcp_lease && link_get_use_dns(link, NETWORK_CONFIG_SOURCE_DHCP4)) {
161✔
544
                        const struct in_addr *dns;
36✔
545
                        union in_addr_union s;
36✔
546
                        int n_dns;
36✔
547

548
                        r = sd_dhcp_lease_get_server_identifier(link->dhcp_lease, &s.in);
36✔
549
                        if (r < 0)
36✔
550
                                return r;
×
551

552
                        n_dns = sd_dhcp_lease_get_dns(link->dhcp_lease, &dns);
36✔
553
                        for (int i = 0; i < n_dns; i++) {
77✔
554
                                r = dns_append_json_one(link,
82✔
555
                                                        &(struct in_addr_full) { .family = AF_INET, .address.in = dns[i], },
41✔
556
                                                        NETWORK_CONFIG_SOURCE_DHCP4,
557
                                                        &s,
558
                                                        &array);
559
                                if (r < 0)
41✔
560
                                        return r;
×
561
                        }
562
                }
563

564
                if (link->dhcp6_lease && link_get_use_dns(link, NETWORK_CONFIG_SOURCE_DHCP6)) {
161✔
565
                        const struct in6_addr *dns;
22✔
566
                        union in_addr_union s;
22✔
567
                        int n_dns;
22✔
568

569
                        r = sd_dhcp6_lease_get_server_address(link->dhcp6_lease, &s.in6);
22✔
570
                        if (r < 0)
22✔
571
                                return r;
×
572

573
                        n_dns = sd_dhcp6_lease_get_dns(link->dhcp6_lease, &dns);
22✔
574
                        for (int i = 0; i < n_dns; i++) {
30✔
575
                                r = dns_append_json_one(link,
16✔
576
                                                        &(struct in_addr_full) { .family = AF_INET6, .address.in6 = dns[i], },
8✔
577
                                                        NETWORK_CONFIG_SOURCE_DHCP6,
578
                                                        &s,
579
                                                        &array);
580
                                if (r < 0)
8✔
581
                                        return r;
×
582
                        }
583
                }
584

585
                if (link_get_use_dns(link, NETWORK_CONFIG_SOURCE_NDISC)) {
161✔
586
                        NDiscRDNSS *a;
150✔
587

588
                        SET_FOREACH(a, link->ndisc_rdnss) {
152✔
589
                                r = dns_append_json_one(link,
4✔
590
                                                        &(struct in_addr_full) { .family = AF_INET6, .address.in6 = a->address, },
2✔
591
                                                        NETWORK_CONFIG_SOURCE_NDISC,
592
                                                        &(union in_addr_union) { .in6 = a->router },
2✔
593
                                                        &array);
594
                                if (r < 0)
2✔
595
                                        return r;
×
596
                        }
597
                }
598
        }
599

600
        return json_variant_set_field_non_null(v, "DNS", array);
163✔
601
}
602

603
static int dnr_append_json_one(Link *link, const struct sd_dns_resolver *res, NetworkConfigSource s, const union in_addr_union *p, sd_json_variant **array) {
6✔
604
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *addrs_array = NULL;
6✔
605
        _cleanup_strv_free_ char **transports = NULL;
6✔
606
        int r;
6✔
607

608
        assert(link);
6✔
609
        assert(res);
6✔
610
        assert(array);
6✔
611

612
        FOREACH_ARRAY(addr, res->addrs, res->n_addrs) {
16✔
613
                r = sd_json_variant_append_arrayb(
30✔
614
                                &addrs_array,
615
                                JSON_BUILD_IN_ADDR(addr, res->family));
10✔
616
                if (r < 0)
10✔
617
                        return r;
618
        }
619

620
        r = dns_resolver_transports_to_strv(res->transports, &transports);
6✔
621
        if (r < 0)
6✔
622
                return r;
623

624
        //FIXME ifindex?
625
        return sd_json_variant_append_arrayb(
12✔
626
                        array,
627
                        SD_JSON_BUILD_OBJECT(
6✔
628
                                        SD_JSON_BUILD_PAIR_INTEGER("Family", res->family),
629
                                        SD_JSON_BUILD_PAIR_INTEGER("Priority", res->priority),
630
                                        JSON_BUILD_PAIR_VARIANT_NON_NULL("Addresses", addrs_array),
631
                                        JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("Port", res->port),
632
                                        JSON_BUILD_PAIR_STRING_NON_EMPTY("ServerName", res->auth_name),
633
                                        JSON_BUILD_PAIR_STRING_NON_EMPTY("DoHPath", res->dohpath),
634
                                        JSON_BUILD_PAIR_STRV_NON_EMPTY("Transports", transports),
635
                                        SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)),
636
                                        JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", p, res->family)));
637
}
638

639
static int dnr_append_json(Link *link, sd_json_variant **v) {
580✔
640
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
580✔
641
        int r;
580✔
642

643
        assert(link);
580✔
644
        assert(v);
580✔
645

646
        if (!link->network)
580✔
647
                return 0;
648

649
        if (link->dhcp_lease && link_get_use_dnr(link, NETWORK_CONFIG_SOURCE_DHCP4)) {
163✔
650
                struct sd_dns_resolver *dnr;
36✔
651
                union in_addr_union s;
36✔
652
                int n_dnr;
36✔
653

654
                r = sd_dhcp_lease_get_server_identifier(link->dhcp_lease, &s.in);
36✔
655
                if (r < 0)
36✔
656
                        return r;
×
657

658
                n_dnr = sd_dhcp_lease_get_dnr(link->dhcp_lease, &dnr);
36✔
659
                if (n_dnr > 0)
36✔
660
                        FOREACH_ARRAY(res, dnr, n_dnr) {
6✔
661
                                r = dnr_append_json_one(link,
4✔
662
                                                        res,
663
                                                        NETWORK_CONFIG_SOURCE_DHCP4,
664
                                                        &s,
665
                                                        &array);
666
                                if (r < 0)
4✔
667
                                        return r;
668
                        }
669
        }
670

671
        if (link->dhcp6_lease && link_get_use_dnr(link, NETWORK_CONFIG_SOURCE_DHCP6)) {
163✔
672
                struct sd_dns_resolver *dnr;
22✔
673
                union in_addr_union s;
22✔
674
                int n_dnr;
22✔
675

676
                r = sd_dhcp6_lease_get_server_address(link->dhcp6_lease, &s.in6);
22✔
677
                if (r < 0)
22✔
678
                        return r;
×
679

680
                n_dnr = sd_dhcp6_lease_get_dnr(link->dhcp6_lease, &dnr);
22✔
681
                if (n_dnr > 0)
22✔
682
                        FOREACH_ARRAY(res, dnr, n_dnr) {
4✔
683
                                r = dnr_append_json_one(link,
2✔
684
                                                        res,
685
                                                        NETWORK_CONFIG_SOURCE_DHCP6,
686
                                                        &s,
687
                                                        &array);
688
                                if (r < 0)
2✔
689
                                        return r;
690
                        }
691
        }
692

693
        if (link_get_use_dnr(link, NETWORK_CONFIG_SOURCE_NDISC)) {
163✔
694
                NDiscDNR *a;
152✔
695

696
                SET_FOREACH(a, link->ndisc_dnr) {
152✔
697
                        r = dnr_append_json_one(link,
×
698
                                                &a->resolver,
×
699
                                                NETWORK_CONFIG_SOURCE_NDISC,
700
                                                &(union in_addr_union) { .in6 = a->router },
×
701
                                                &array);
702
                        if (r < 0)
×
703
                                return r;
×
704
                }
705
        }
706

707
        return json_variant_set_field_non_null(v, "DNR", array);
163✔
708
}
709

710
static int server_append_json_one_addr(int family, const union in_addr_union *a, NetworkConfigSource s, const union in_addr_union *p, sd_json_variant **array) {
45✔
711
        assert(IN_SET(family, AF_INET, AF_INET6));
45✔
712
        assert(a);
45✔
713
        assert(array);
45✔
714

715
        return sd_json_variant_append_arraybo(
45✔
716
                        array,
717
                        SD_JSON_BUILD_PAIR_INTEGER("Family", family),
718
                        JSON_BUILD_PAIR_IN_ADDR("Address", a, family),
719
                        SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)),
720
                        JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", p, family));
721
}
722

723
static int server_append_json_one_fqdn(int family, const char *fqdn, NetworkConfigSource s, const union in_addr_union *p, sd_json_variant **array) {
8✔
724
        assert(IN_SET(family, AF_UNSPEC, AF_INET, AF_INET6));
8✔
725
        assert(fqdn);
8✔
726
        assert(array);
8✔
727

728
        return sd_json_variant_append_arraybo(
8✔
729
                        array,
730
                        SD_JSON_BUILD_PAIR_STRING("Server", fqdn),
731
                        SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)),
732
                        JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", p, family));
733
}
734

735
static int server_append_json_one_string(const char *str, NetworkConfigSource s, sd_json_variant **array) {
8✔
736
        union in_addr_union a;
8✔
737
        int family;
8✔
738

739
        assert(str);
8✔
740

741
        if (in_addr_from_string_auto(str, &family, &a) >= 0)
8✔
742
                return server_append_json_one_addr(family, &a, s, NULL, array);
×
743

744
        return server_append_json_one_fqdn(AF_UNSPEC, str, s, NULL, array);
8✔
745
}
746

747
static int ntp_append_json(Link *link, sd_json_variant **v) {
580✔
748
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
580✔
749
        int r;
580✔
750

751
        assert(link);
580✔
752
        assert(v);
580✔
753

754
        if (!link->network)
580✔
755
                return 0;
756

757
        STRV_FOREACH(p, link->ntp ?: link->network->ntp) {
334✔
758
                r = server_append_json_one_string(*p, NETWORK_CONFIG_SOURCE_RUNTIME, &array);
8✔
759
                if (r < 0)
8✔
760
                        return r;
761
        }
762

763
        if (!link->ntp) {
163✔
764
                if (link->dhcp_lease && link_get_use_ntp(link, NETWORK_CONFIG_SOURCE_DHCP4)) {
162✔
765
                        const struct in_addr *ntp;
40✔
766
                        union in_addr_union s;
40✔
767
                        int n_ntp;
40✔
768

769
                        r = sd_dhcp_lease_get_server_identifier(link->dhcp_lease, &s.in);
40✔
770
                        if (r < 0)
40✔
771
                                return r;
×
772

773
                        n_ntp = sd_dhcp_lease_get_ntp(link->dhcp_lease, &ntp);
40✔
774
                        for (int i = 0; i < n_ntp; i++) {
74✔
775
                                r = server_append_json_one_addr(AF_INET,
68✔
776
                                                                &(union in_addr_union) { .in = ntp[i], },
34✔
777
                                                                NETWORK_CONFIG_SOURCE_DHCP4,
778
                                                                &s,
779
                                                                &array);
780
                                if (r < 0)
34✔
781
                                        return r;
×
782
                        }
783
                }
784

785
                if (link->dhcp6_lease && link_get_use_ntp(link, NETWORK_CONFIG_SOURCE_DHCP6)) {
162✔
786
                        const struct in6_addr *ntp_addr;
26✔
787
                        union in_addr_union s;
26✔
788
                        char **ntp_fqdn;
26✔
789
                        int n_ntp;
26✔
790

791
                        r = sd_dhcp6_lease_get_server_address(link->dhcp6_lease, &s.in6);
26✔
792
                        if (r < 0)
26✔
793
                                return r;
×
794

795
                        n_ntp = sd_dhcp6_lease_get_ntp_addrs(link->dhcp6_lease, &ntp_addr);
26✔
796
                        for (int i = 0; i < n_ntp; i++) {
29✔
797
                                r = server_append_json_one_addr(AF_INET6,
6✔
798
                                                                &(union in_addr_union) { .in6 = ntp_addr[i], },
3✔
799
                                                                NETWORK_CONFIG_SOURCE_DHCP6,
800
                                                                &s,
801
                                                                &array);
802
                                if (r < 0)
3✔
803
                                        return r;
×
804
                        }
805

806
                        n_ntp = sd_dhcp6_lease_get_ntp_fqdn(link->dhcp6_lease, &ntp_fqdn);
26✔
807
                        for (int i = 0; i < n_ntp; i++) {
26✔
808
                                r = server_append_json_one_fqdn(AF_INET6,
×
809
                                                                ntp_fqdn[i],
×
810
                                                                NETWORK_CONFIG_SOURCE_DHCP6,
811
                                                                &s,
812
                                                                &array);
813
                                if (r < 0)
×
814
                                        return r;
815
                        }
816
                }
817
        }
818

819
        return json_variant_set_field_non_null(v, "NTP", array);
163✔
820
}
821

822
static int domain_append_json(int family, const char *domain, NetworkConfigSource s, const union in_addr_union *p, sd_json_variant **array) {
16✔
823
        assert(IN_SET(family, AF_UNSPEC, AF_INET, AF_INET6));
16✔
824
        assert(domain);
16✔
825
        assert(array);
16✔
826

827
        return sd_json_variant_append_arraybo(
16✔
828
                        array,
829
                        SD_JSON_BUILD_PAIR_STRING("Domain", domain),
830
                        SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)),
831
                        JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", p, family));
832
}
833

834
static int sip_append_json(Link *link, sd_json_variant **v) {
580✔
835
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
580✔
836
        int r;
580✔
837

838
        assert(link);
580✔
839
        assert(v);
580✔
840

841
        if (!link->network)
580✔
842
                return 0;
843

844
        if (link->dhcp_lease && link->network->dhcp_use_sip) {
163✔
845
                const struct in_addr *sip;
38✔
846
                union in_addr_union s;
38✔
847
                int n_sip;
38✔
848

849
                n_sip = sd_dhcp_lease_get_sip(link->dhcp_lease, &sip);
38✔
850
                if (n_sip <= 0)
38✔
851
                        return 0;
34✔
852

853
                r = sd_dhcp_lease_get_server_identifier(link->dhcp_lease, &s.in);
4✔
854
                if (r < 0)
4✔
855
                        return r;
856

857
                for (int i = 0; i < n_sip; i++) {
10✔
858
                        r = server_append_json_one_addr(AF_INET,
12✔
859
                                                        &(union in_addr_union) { .in = sip[i], },
6✔
860
                                                        NETWORK_CONFIG_SOURCE_DHCP4,
861
                                                        &s,
862
                                                        &array);
863
                        if (r < 0)
6✔
864
                                return r;
×
865
                }
866

867
        }
868

869
        if (link->dhcp6_lease && link->network->dhcp6_use_sip) {
129✔
870
                const struct in6_addr *sip_addr;
8✔
871
                union in_addr_union s;
8✔
872
                char **domains;
8✔
873
                int n_sip;
8✔
874

875
                r = sd_dhcp6_lease_get_server_address(link->dhcp6_lease, &s.in6);
8✔
876
                if (r < 0)
8✔
877
                        return r;
×
878

879
                n_sip = sd_dhcp6_lease_get_sip_addrs(link->dhcp6_lease, &sip_addr);
8✔
880
                for (int i = 0; i < n_sip; i++) {
10✔
881
                        r = server_append_json_one_addr(AF_INET6,
4✔
882
                                                        &(union in_addr_union) { .in6 = sip_addr[i], },
2✔
883
                                                        NETWORK_CONFIG_SOURCE_DHCP6,
884
                                                        &s,
885
                                                        &array);
886
                        if (r < 0)
2✔
887
                                return r;
×
888
                }
889

890
                if (sd_dhcp6_lease_get_sip_domains(link->dhcp6_lease, &domains) >= 0)
8✔
891
                        STRV_FOREACH(p, domains) {
4✔
892
                                r = domain_append_json(AF_INET6,
2✔
893
                                                       *p,
894
                                                       NETWORK_CONFIG_SOURCE_DHCP6,
895
                                                       &s,
896
                                                       &array);
897
                                if (r < 0)
2✔
898
                                        return r;
899
                        }
900

901
        }
902

903
        return json_variant_set_field_non_null(v, "SIP", array);
129✔
904
}
905

906
static int domains_append_json(Link *link, bool is_route, sd_json_variant **v) {
1,160✔
907
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
1,160✔
908
        OrderedSet *link_domains, *network_domains;
1,160✔
909
        UseDomains use_domains;
1,160✔
910
        union in_addr_union s;
1,160✔
911
        char **domains;
1,160✔
912
        const char *domain;
1,160✔
913
        int r;
1,160✔
914

915
        assert(link);
1,160✔
916
        assert(v);
1,160✔
917

918
        if (!link->network)
1,160✔
919
                return 0;
920

921
        link_domains = is_route ? link->route_domains : link->search_domains;
326✔
922
        network_domains = is_route ? link->network->route_domains : link->network->search_domains;
326✔
923
        use_domains = is_route ? USE_DOMAINS_ROUTE : USE_DOMAINS_YES;
326✔
924

925
        ORDERED_SET_FOREACH(domain, link_domains ?: network_domains) {
672✔
926
                r = domain_append_json(AF_UNSPEC, domain,
16✔
927
                                       link_domains ? NETWORK_CONFIG_SOURCE_RUNTIME : NETWORK_CONFIG_SOURCE_STATIC,
928
                                       NULL, &array);
929
                if (r < 0)
10✔
930
                        return r;
×
931
        }
932

933
        if (!link_domains) {
326✔
934
                if (link->dhcp_lease &&
402✔
935
                    link_get_use_domains(link, NETWORK_CONFIG_SOURCE_DHCP4) == use_domains) {
80✔
936
                        r = sd_dhcp_lease_get_server_identifier(link->dhcp_lease, &s.in);
2✔
937
                        if (r < 0)
2✔
938
                                return r;
939

940
                        if (sd_dhcp_lease_get_domainname(link->dhcp_lease, &domain) >= 0) {
2✔
941
                                r = domain_append_json(AF_INET, domain, NETWORK_CONFIG_SOURCE_DHCP4, &s, &array);
×
942
                                if (r < 0)
×
943
                                        return r;
944
                        }
945

946
                        if (sd_dhcp_lease_get_search_domains(link->dhcp_lease, &domains) >= 0)
2✔
947
                                STRV_FOREACH(p, domains) {
4✔
948
                                        r = domain_append_json(AF_INET, *p, NETWORK_CONFIG_SOURCE_DHCP4, &s, &array);
2✔
949
                                        if (r < 0)
2✔
950
                                                return r;
951
                                }
952
                }
953

954
                if (link->dhcp6_lease &&
374✔
955
                    link_get_use_domains(link, NETWORK_CONFIG_SOURCE_DHCP6) == use_domains) {
52✔
956
                        r = sd_dhcp6_lease_get_server_address(link->dhcp6_lease, &s.in6);
×
957
                        if (r < 0)
×
958
                                return r;
959

960
                        if (sd_dhcp6_lease_get_domains(link->dhcp6_lease, &domains) >= 0)
×
961
                                STRV_FOREACH(p, domains) {
×
962
                                        r = domain_append_json(AF_INET6, *p, NETWORK_CONFIG_SOURCE_DHCP6, &s, &array);
×
963
                                        if (r < 0)
×
964
                                                return r;
965
                                }
966
                }
967

968
                if (link_get_use_domains(link, NETWORK_CONFIG_SOURCE_NDISC) == use_domains) {
322✔
969
                        NDiscDNSSL *a;
2✔
970

971
                        SET_FOREACH(a, link->ndisc_dnssl) {
4✔
972
                                r = domain_append_json(AF_INET6, ndisc_dnssl_domain(a), NETWORK_CONFIG_SOURCE_NDISC,
2✔
973
                                                       &(union in_addr_union) { .in6 = a->router },
2✔
974
                                                       &array);
975
                                if (r < 0)
2✔
976
                                        return r;
×
977
                        }
978
                }
979
        }
980

981
        return json_variant_set_field_non_null(v, is_route ? "RouteDomains" : "SearchDomains", array);
489✔
982
}
983

984
static int nta_append_json(const char *nta, NetworkConfigSource s, sd_json_variant **array) {
×
985
        assert(nta);
×
986
        assert(array);
×
987

988
        return sd_json_variant_append_arraybo(
×
989
                        array,
990
                        SD_JSON_BUILD_PAIR_STRING("DNSSECNegativeTrustAnchor", nta),
991
                        SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)));
992
}
993

994
static int ntas_append_json(Link *link, sd_json_variant **v) {
580✔
995
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
580✔
996
        const char *nta;
580✔
997
        int r;
580✔
998

999
        assert(link);
580✔
1000
        assert(v);
580✔
1001

1002
        if (!link->network)
580✔
1003
                return 0;
1004

1005
        SET_FOREACH(nta, link->dnssec_negative_trust_anchors ?: link->network->dnssec_negative_trust_anchors) {
326✔
1006
                r = nta_append_json(nta,
×
1007
                                   link->dnssec_negative_trust_anchors ? NETWORK_CONFIG_SOURCE_RUNTIME : NETWORK_CONFIG_SOURCE_STATIC,
×
1008
                                   &array);
1009
                if (r < 0)
×
1010
                        return r;
×
1011
        }
1012

1013
        return json_variant_set_field_non_null(v, "DNSSECNegativeTrustAnchors", array);
163✔
1014
}
1015

1016
static int dns_misc_append_json(Link *link, sd_json_variant **v) {
580✔
1017
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
580✔
1018
        ResolveSupport resolve_support;
580✔
1019
        NetworkConfigSource source;
580✔
1020
        DnsOverTlsMode mode;
580✔
1021
        int t, r;
580✔
1022

1023
        assert(link);
580✔
1024
        assert(v);
580✔
1025

1026
        if (!link->network)
580✔
1027
                return 0;
1028

1029
        resolve_support = link->llmnr >= 0 ? link->llmnr : link->network->llmnr;
163✔
1030
        if (resolve_support >= 0) {
163✔
1031
                source = link->llmnr >= 0 ? NETWORK_CONFIG_SOURCE_RUNTIME : NETWORK_CONFIG_SOURCE_STATIC;
163✔
1032

1033
                r = sd_json_variant_append_arraybo(
163✔
1034
                                &array,
1035
                                SD_JSON_BUILD_PAIR_STRING("LLMNR", resolve_support_to_string(resolve_support)),
1036
                                SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(source)));
1037
                if (r < 0)
163✔
1038
                        return r;
1039
        }
1040

1041
        resolve_support = link->mdns >= 0 ? link->mdns : link->network->mdns;
163✔
1042
        if (resolve_support >= 0) {
163✔
1043
                source = link->mdns >= 0 ? NETWORK_CONFIG_SOURCE_RUNTIME : NETWORK_CONFIG_SOURCE_STATIC;
163✔
1044

1045
                r = sd_json_variant_append_arraybo(
163✔
1046
                                &array,
1047
                                SD_JSON_BUILD_PAIR_STRING("MDNS", resolve_support_to_string(resolve_support)),
1048
                                SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(source)));
1049
                if (r < 0)
163✔
1050
                        return r;
1051
        }
1052

1053
        t = link->dns_default_route >= 0 ? link->dns_default_route : link->network->dns_default_route;
163✔
1054
        if (t >= 0) {
163✔
1055
                source = link->dns_default_route >= 0 ? NETWORK_CONFIG_SOURCE_RUNTIME : NETWORK_CONFIG_SOURCE_STATIC;
×
1056

1057
                r = sd_json_variant_append_arraybo(
×
1058
                                &array,
1059
                                SD_JSON_BUILD_PAIR_BOOLEAN("DNSDefaultRoute", t),
1060
                                SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(source)));
1061
                if (r < 0)
×
1062
                        return r;
1063
        }
1064

1065
        mode = link->dns_over_tls_mode >= 0 ? link->dns_over_tls_mode : link->network->dns_over_tls_mode;
163✔
1066
        if (mode >= 0) {
163✔
1067
                source = link->dns_over_tls_mode >= 0 ? NETWORK_CONFIG_SOURCE_RUNTIME : NETWORK_CONFIG_SOURCE_STATIC;
×
1068

1069
                r = sd_json_variant_append_arraybo(
×
1070
                                &array,
1071
                                SD_JSON_BUILD_PAIR_STRING("DNSOverTLS", dns_over_tls_mode_to_string(mode)),
1072
                                SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(source)));
1073
                if (r < 0)
×
1074
                        return r;
1075
        }
1076

1077
        return json_variant_set_field_non_null(v, "DNSSettings", array);
163✔
1078
}
1079

1080
static int captive_portal_append_json(Link *link, sd_json_variant **v) {
580✔
1081
        const char *captive_portal;
580✔
1082
        int r;
580✔
1083

1084
        assert(link);
580✔
1085
        assert(v);
580✔
1086

1087
        r = link_get_captive_portal(link, &captive_portal);
580✔
1088
        if (r <= 0)
580✔
1089
                return r;
580✔
1090

1091
        return sd_json_variant_merge_objectbo(v, SD_JSON_BUILD_PAIR_STRING("CaptivePortal", captive_portal));
3✔
1092
}
1093

1094
static int pref64_append_json(Link *link, sd_json_variant **v) {
580✔
1095
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL, *w = NULL;
582✔
1096
        NDiscPREF64 *i;
580✔
1097
        int r;
580✔
1098

1099
        assert(link);
580✔
1100
        assert(v);
580✔
1101

1102
        if (!link->network || !link->network->ndisc_use_pref64)
580✔
1103
                return 0;
1104

1105
        SET_FOREACH(i, link->ndisc_pref64) {
4✔
1106
                r = sd_json_variant_append_arraybo(
2✔
1107
                                &array,
1108
                                JSON_BUILD_PAIR_IN6_ADDR_NON_NULL("Prefix", &i->prefix),
1109
                                SD_JSON_BUILD_PAIR_UNSIGNED("PrefixLength", i->prefix_len),
1110
                                JSON_BUILD_PAIR_FINITE_USEC("LifetimeUSec", i->lifetime_usec),
1111
                                JSON_BUILD_PAIR_IN6_ADDR_NON_NULL("ConfigProvider", &i->router));
1112
                if (r < 0)
2✔
1113
                        return r;
×
1114
        }
1115

1116
        r = json_variant_set_field_non_null(&w, "PREF64", array);
2✔
1117
        if (r < 0)
2✔
1118
                return r;
1119

1120
        return json_variant_set_field_non_null(v, "NDisc", w);
2✔
1121
}
1122

1123
static int dhcp_server_append_json(Link *link, sd_json_variant **v) {
580✔
1124
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *w = NULL;
580✔
1125
        int r;
580✔
1126

1127
        assert(link);
580✔
1128
        assert(v);
580✔
1129

1130
        if (!link->dhcp_server)
580✔
1131
                return 0;
1132

1133
        r = sd_json_buildo(
1✔
1134
                        &w,
1135
                        SD_JSON_BUILD_PAIR_UNSIGNED("PoolOffset", link->dhcp_server->pool_offset),
1136
                        SD_JSON_BUILD_PAIR_UNSIGNED("PoolSize", link->dhcp_server->pool_size));
1137
        if (r < 0)
1✔
1138
                return r;
1139

1140
        r = dhcp_server_bound_leases_append_json(link->dhcp_server, &w);
1✔
1141
        if (r < 0)
1✔
1142
                return r;
1143

1144
        r = dhcp_server_static_leases_append_json(link->dhcp_server, &w);
1✔
1145
        if (r < 0)
1✔
1146
                return r;
1147

1148
        return json_variant_set_field_non_null(v, "DHCPServer", w);
1✔
1149
}
1150

1151
static int dhcp6_client_vendor_options_append_json(Link *link, sd_json_variant **v) {
29✔
1152
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
29✔
1153
        sd_dhcp6_option **options = NULL;
29✔
1154
        int r, n_vendor_options;
29✔
1155

1156
        assert(link);
29✔
1157
        assert(v);
29✔
1158

1159
        if (!link->dhcp6_lease)
29✔
1160
                return 0;
1161

1162
        n_vendor_options = sd_dhcp6_lease_get_vendor_options(link->dhcp6_lease, &options);
26✔
1163

1164
        FOREACH_ARRAY(option, options, n_vendor_options) {
26✔
1165
                r = sd_json_variant_append_arraybo(
×
1166
                                &array,
1167
                                SD_JSON_BUILD_PAIR_UNSIGNED("EnterpriseId", (*option)->enterprise_identifier),
1168
                                SD_JSON_BUILD_PAIR_UNSIGNED("SubOptionCode", (*option)->option),
1169
                                SD_JSON_BUILD_PAIR_HEX("SubOptionData", (*option)->data, (*option)->length));
1170
                if (r < 0)
×
1171
                        return r;
1172
        }
1173

1174
        return json_variant_set_field_non_null(v, "VendorSpecificOptions", array);
26✔
1175
}
1176

1177
static int dhcp6_client_lease_append_json(Link *link, sd_json_variant **v) {
29✔
1178
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *w = NULL;
29✔
1179
        usec_t ts = USEC_INFINITY, t1 = USEC_INFINITY, t2 = USEC_INFINITY;
29✔
1180
        int r;
29✔
1181

1182
        assert(link);
29✔
1183
        assert(v);
29✔
1184

1185
        if (!link->dhcp6_lease)
29✔
1186
                return 0;
1187

1188
        r = sd_dhcp6_lease_get_timestamp(link->dhcp6_lease, CLOCK_BOOTTIME, &ts);
26✔
1189
        if (r < 0 && r != -ENODATA)
26✔
1190
                return r;
1191

1192
        r = sd_dhcp6_lease_get_t1_timestamp(link->dhcp6_lease, CLOCK_BOOTTIME, &t1);
26✔
1193
        if (r < 0 && r != -ENODATA)
26✔
1194
                return r;
1195

1196
        r = sd_dhcp6_lease_get_t2_timestamp(link->dhcp6_lease, CLOCK_BOOTTIME, &t2);
26✔
1197
        if (r < 0 && r != -ENODATA)
26✔
1198
                return r;
1199

1200
        r = sd_json_buildo(
26✔
1201
                        &w,
1202
                        JSON_BUILD_PAIR_FINITE_USEC("Timeout1USec", t1),
1203
                        JSON_BUILD_PAIR_FINITE_USEC("Timeout2USec", t2),
1204
                        JSON_BUILD_PAIR_FINITE_USEC("LeaseTimestampUSec", ts));
1205
        if (r < 0)
26✔
1206
                return r;
1207

1208
        return json_variant_set_field_non_null(v, "Lease", w);
26✔
1209
}
1210

1211
static int dhcp6_client_pd_append_json(Link *link, sd_json_variant **v) {
29✔
1212
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
29✔
1213
        int r;
29✔
1214

1215
        assert(link);
29✔
1216
        assert(link->network);
29✔
1217
        assert(v);
29✔
1218

1219
        if (!link->network->dhcp6_use_pd_prefix ||
58✔
1220
            !sd_dhcp6_lease_has_pd_prefix(link->dhcp6_lease))
29✔
1221
                return 0;
26✔
1222

1223
        FOREACH_DHCP6_PD_PREFIX(link->dhcp6_lease) {
6✔
1224
                usec_t lifetime_preferred_usec, lifetime_valid_usec;
3✔
1225
                struct in6_addr prefix;
3✔
1226
                uint8_t prefix_len;
3✔
1227

1228
                r = sd_dhcp6_lease_get_pd_prefix(link->dhcp6_lease, &prefix, &prefix_len);
3✔
1229
                if (r < 0)
3✔
1230
                        return r;
×
1231

1232
                r = sd_dhcp6_lease_get_pd_lifetime_timestamp(link->dhcp6_lease, CLOCK_BOOTTIME,
3✔
1233
                                                             &lifetime_preferred_usec, &lifetime_valid_usec);
1234
                if (r < 0)
3✔
1235
                        return r;
1236

1237
                r = sd_json_variant_append_arraybo(
3✔
1238
                                &array,
1239
                                JSON_BUILD_PAIR_IN6_ADDR("Prefix", &prefix),
1240
                                SD_JSON_BUILD_PAIR_UNSIGNED("PrefixLength", prefix_len),
1241
                                JSON_BUILD_PAIR_FINITE_USEC("PreferredLifetimeUSec", lifetime_preferred_usec),
1242
                                JSON_BUILD_PAIR_FINITE_USEC("ValidLifetimeUSec", lifetime_valid_usec));
1243
                if (r < 0)
3✔
1244
                        return r;
1245
        }
1246

1247
        return json_variant_set_field_non_null(v, "Prefixes", array);
3✔
1248
}
1249

1250
static int dhcp6_client_duid_append_json(Link *link, sd_json_variant **v) {
29✔
1251
        const sd_dhcp_duid *duid;
29✔
1252
        const void *data;
29✔
1253
        size_t data_size;
29✔
1254
        int r;
29✔
1255

1256
        assert(link);
29✔
1257
        assert(v);
29✔
1258

1259
        if (!link->dhcp6_client)
29✔
1260
                return 0;
29✔
1261

1262
        r = sd_dhcp6_client_get_duid(link->dhcp6_client, &duid);
29✔
1263
        if (r < 0)
29✔
1264
                return 0;
1265

1266
        r = sd_dhcp_duid_get_raw(duid, &data, &data_size);
29✔
1267
        if (r < 0)
29✔
1268
                return 0;
1269

1270
        return sd_json_variant_merge_objectbo(v, SD_JSON_BUILD_PAIR_BYTE_ARRAY("DUID", data, data_size));
29✔
1271
}
1272

1273
static int dhcp6_client_append_json(Link *link, sd_json_variant **v) {
580✔
1274
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *w = NULL;
580✔
1275
        int r;
580✔
1276

1277
        assert(link);
580✔
1278
        assert(v);
580✔
1279

1280
        if (!link->dhcp6_client)
580✔
1281
                return 0;
1282

1283
        r = dhcp6_client_lease_append_json(link, &w);
29✔
1284
        if (r < 0)
29✔
1285
                return r;
1286

1287
        r = dhcp6_client_pd_append_json(link, &w);
29✔
1288
        if (r < 0)
29✔
1289
                return r;
1290

1291
        r = dhcp6_client_vendor_options_append_json(link, &w);
29✔
1292
        if (r < 0)
29✔
1293
                return r;
1294

1295
        r = dhcp6_client_duid_append_json(link, &w);
29✔
1296
        if (r < 0)
29✔
1297
                return r;
1298

1299
        return json_variant_set_field_non_null(v, "DHCPv6Client", w);
29✔
1300
}
1301

1302
static int dhcp_client_lease_append_json(Link *link, sd_json_variant **v) {
43✔
1303
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *w = NULL;
43✔
1304
        usec_t lease_timestamp_usec = USEC_INFINITY, t1 = USEC_INFINITY, t2 = USEC_INFINITY;
43✔
1305
        int r;
43✔
1306

1307
        assert(link);
43✔
1308
        assert(v);
43✔
1309

1310
        if (!link->dhcp_client || !link->dhcp_lease)
43✔
1311
                return 0;
1312

1313
        r = sd_dhcp_lease_get_timestamp(link->dhcp_lease, CLOCK_BOOTTIME, &lease_timestamp_usec);
40✔
1314
        if (r < 0 && r != -ENODATA)
40✔
1315
                return r;
1316

1317
        r = sd_dhcp_lease_get_t1_timestamp(link->dhcp_lease, CLOCK_BOOTTIME, &t1);
40✔
1318
        if (r < 0 && r != -ENODATA)
40✔
1319
                return r;
1320

1321
        r = sd_dhcp_lease_get_t2_timestamp(link->dhcp_lease, CLOCK_BOOTTIME, &t2);
40✔
1322
        if (r < 0 && r != -ENODATA)
40✔
1323
                return r;
1324

1325
        r = sd_json_buildo(&w,
40✔
1326
                           JSON_BUILD_PAIR_FINITE_USEC("LeaseTimestampUSec", lease_timestamp_usec),
1327
                           JSON_BUILD_PAIR_FINITE_USEC("Timeout1USec", t1),
1328
                           JSON_BUILD_PAIR_FINITE_USEC("Timeout2USec", t2));
1329
        if (r < 0)
40✔
1330
                return r;
1331

1332
        return json_variant_set_field_non_null(v, "Lease", w);
40✔
1333
}
1334

1335
static int dhcp_client_pd_append_json(Link *link, sd_json_variant **v) {
43✔
1336
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *addresses = NULL, *array = NULL;
44✔
1337
        uint8_t ipv4masklen, sixrd_prefixlen;
43✔
1338
        struct in6_addr sixrd_prefix;
43✔
1339
        const struct in_addr *br_addresses;
43✔
1340
        size_t n_br_addresses = 0;
43✔
1341
        int r;
43✔
1342

1343
        assert(link);
43✔
1344
        assert(link->network);
43✔
1345
        assert(v);
43✔
1346

1347
        if (!link->network->dhcp_use_6rd || !sd_dhcp_lease_has_6rd(link->dhcp_lease))
43✔
1348
                return 0;
42✔
1349

1350
        r = sd_dhcp_lease_get_6rd(link->dhcp_lease, &ipv4masklen, &sixrd_prefixlen, &sixrd_prefix, &br_addresses, &n_br_addresses);
1✔
1351
        if (r < 0)
1✔
1352
                return r;
1353

1354
        FOREACH_ARRAY(br_address, br_addresses, n_br_addresses) {
2✔
1355
                r = sd_json_variant_append_arrayb(&addresses, JSON_BUILD_IN4_ADDR(br_address));
1✔
1356
                if (r < 0)
1✔
1357
                        return r;
1358
        }
1359

1360
        r = sd_json_buildo(
1✔
1361
                        &array,
1362
                        JSON_BUILD_PAIR_IN6_ADDR("Prefix", &sixrd_prefix),
1363
                        SD_JSON_BUILD_PAIR_UNSIGNED("PrefixLength", sixrd_prefixlen),
1364
                        SD_JSON_BUILD_PAIR_UNSIGNED("IPv4MaskLength", ipv4masklen),
1365
                        JSON_BUILD_PAIR_VARIANT_NON_NULL("BorderRouters", addresses));
1366
        if (r < 0)
1✔
1367
                return r;
1368

1369
        return json_variant_set_field_non_null(v, "6rdPrefix", array);
1✔
1370
}
1371

1372
static int dhcp_client_private_options_append_json(Link *link, sd_json_variant **v) {
43✔
1373
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
43✔
1374
        int r;
43✔
1375

1376
        assert(link);
43✔
1377
        assert(v);
43✔
1378

1379
        if (!link->dhcp_lease)
43✔
1380
                return 0;
1381

1382
        LIST_FOREACH(options, option, link->dhcp_lease->private_options) {
40✔
1383

1384
                r = sd_json_variant_append_arraybo(
×
1385
                                &array,
1386
                                SD_JSON_BUILD_PAIR_UNSIGNED("Option", option->tag),
1387
                                SD_JSON_BUILD_PAIR_HEX("PrivateOptionData", option->data, option->length));
1388
                if (r < 0)
×
1389
                        return 0;
1390
        }
1391
        return json_variant_set_field_non_null(v, "PrivateOptions", array);
40✔
1392
}
1393

1394
static int dhcp_client_id_append_json(Link *link, sd_json_variant **v) {
43✔
1395
        const sd_dhcp_client_id *client_id;
43✔
1396
        const void *data;
43✔
1397
        size_t l;
43✔
1398
        int r;
43✔
1399

1400
        assert(link);
43✔
1401
        assert(v);
43✔
1402

1403
        if (!link->dhcp_client)
43✔
1404
                return 0;
43✔
1405

1406
        r = sd_dhcp_client_get_client_id(link->dhcp_client, &client_id);
43✔
1407
        if (r < 0)
43✔
1408
                return 0;
1409

1410
        r = sd_dhcp_client_id_get_raw(client_id, &data, &l);
43✔
1411
        if (r < 0)
43✔
1412
                return 0;
1413

1414
        return sd_json_variant_merge_objectbo(v, SD_JSON_BUILD_PAIR_BYTE_ARRAY("ClientIdentifier", data, l));
43✔
1415
}
1416

1417
static int dhcp_client_append_json(Link *link, sd_json_variant **v) {
580✔
1418
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *w = NULL;
580✔
1419
        int r;
580✔
1420

1421
        assert(link);
580✔
1422
        assert(v);
580✔
1423

1424
        if (!link->dhcp_client)
580✔
1425
                return 0;
1426

1427
        r = dhcp_client_lease_append_json(link, &w);
43✔
1428
        if (r < 0)
43✔
1429
                return r;
1430

1431
        r = dhcp_client_pd_append_json(link, &w);
43✔
1432
        if (r < 0)
43✔
1433
                return r;
1434

1435
        r = dhcp_client_private_options_append_json(link, &w);
43✔
1436
        if (r < 0)
43✔
1437
                return r;
1438

1439
        r = dhcp_client_id_append_json(link, &w);
43✔
1440
        if (r < 0)
43✔
1441
                return r;
1442

1443
        return json_variant_set_field_non_null(v, "DHCPv4Client", w);
43✔
1444
}
1445

1446
static int lldp_tx_append_json(Link *link, sd_json_variant **v) {
580✔
1447
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *w = NULL;
580✔
1448
        int r;
580✔
1449

1450
        assert(link);
580✔
1451
        assert(v);
580✔
1452

1453
        if (!link->lldp_tx)
580✔
1454
                return 0;
1455

1456
        r = sd_lldp_tx_describe(link->lldp_tx, &w);
1✔
1457
        if (r < 0)
1✔
1458
                return r;
1459

1460
        return json_variant_set_field_non_null(v, "LLDP", w);
1✔
1461
}
1462

1463
int link_build_json(Link *link, sd_json_variant **ret) {
580✔
1464
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
580✔
1465
        _cleanup_free_ char *type = NULL, *flags = NULL;
580✔
1466
        int r;
580✔
1467

1468
        assert(link);
580✔
1469
        assert(ret);
580✔
1470

1471
        r = net_get_type_string(link->dev, link->iftype, &type);
580✔
1472
        if (r == -ENOMEM)
580✔
1473
                return r;
1474

1475
        r = link_flags_to_string_alloc(link->flags, &flags);
580✔
1476
        if (r < 0)
580✔
1477
                return r;
1478

1479
        r = sd_json_buildo(
580✔
1480
                        &v,
1481
                        /* basic information */
1482
                        SD_JSON_BUILD_PAIR_INTEGER("Index", link->ifindex),
1483
                        SD_JSON_BUILD_PAIR_STRING("Name", link->ifname),
1484
                        JSON_BUILD_PAIR_STRV_NON_EMPTY("AlternativeNames", link->alternative_names),
1485
                        SD_JSON_BUILD_PAIR_CONDITION(link->master_ifindex > 0,
1486
                                                     "MasterInterfaceIndex", SD_JSON_BUILD_INTEGER(link->master_ifindex)),
1487
                        JSON_BUILD_PAIR_STRING_NON_EMPTY("Kind", link->kind),
1488
                        SD_JSON_BUILD_PAIR_STRING("Type", type),
1489
                        JSON_BUILD_PAIR_STRING_NON_EMPTY("Driver", link->driver),
1490
                        SD_JSON_BUILD_PAIR_UNSIGNED("Flags", link->flags),
1491
                        SD_JSON_BUILD_PAIR_STRING("FlagsString", flags),
1492
                        SD_JSON_BUILD_PAIR_UNSIGNED("KernelOperationalState", link->kernel_operstate),
1493
                        SD_JSON_BUILD_PAIR_STRING("KernelOperationalStateString", kernel_operstate_to_string(link->kernel_operstate)),
1494
                        SD_JSON_BUILD_PAIR_UNSIGNED("MTU", link->mtu),
1495
                        SD_JSON_BUILD_PAIR_UNSIGNED("MinimumMTU", link->min_mtu),
1496
                        SD_JSON_BUILD_PAIR_UNSIGNED("MaximumMTU", link->max_mtu),
1497
                        JSON_BUILD_PAIR_HW_ADDR_NON_NULL("HardwareAddress", &link->hw_addr),
1498
                        JSON_BUILD_PAIR_HW_ADDR_NON_NULL("PermanentHardwareAddress", &link->permanent_hw_addr),
1499
                        JSON_BUILD_PAIR_HW_ADDR_NON_NULL("BroadcastAddress", &link->bcast_addr),
1500
                        JSON_BUILD_PAIR_IN6_ADDR_NON_NULL("IPv6LinkLocalAddress", &link->ipv6ll_address),
1501
                        /* wlan information */
1502
                        SD_JSON_BUILD_PAIR_CONDITION(link->wlan_iftype > 0, "WirelessLanInterfaceType",
1503
                                                     SD_JSON_BUILD_UNSIGNED(link->wlan_iftype)),
1504
                        SD_JSON_BUILD_PAIR_CONDITION(link->wlan_iftype > 0, "WirelessLanInterfaceTypeString",
1505
                                                     SD_JSON_BUILD_STRING(nl80211_iftype_to_string(link->wlan_iftype))),
1506
                        JSON_BUILD_PAIR_STRING_NON_EMPTY("SSID", link->ssid),
1507
                        JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL("BSSID", &link->bssid),
1508
                        /* link state */
1509
                        SD_JSON_BUILD_PAIR_STRING("AdministrativeState", link_state_to_string(link->state)),
1510
                        SD_JSON_BUILD_PAIR_STRING("OperationalState", link_operstate_to_string(link->operstate)),
1511
                        SD_JSON_BUILD_PAIR_STRING("CarrierState", link_carrier_state_to_string(link->carrier_state)),
1512
                        SD_JSON_BUILD_PAIR_STRING("AddressState", link_address_state_to_string(link->address_state)),
1513
                        SD_JSON_BUILD_PAIR_STRING("IPv4AddressState", link_address_state_to_string(link->ipv4_address_state)),
1514
                        SD_JSON_BUILD_PAIR_STRING("IPv6AddressState", link_address_state_to_string(link->ipv6_address_state)),
1515
                        SD_JSON_BUILD_PAIR_STRING("OnlineState", link_online_state_to_string(link->online_state)));
1516
        if (r < 0)
580✔
1517
                return r;
1518

1519
        r = network_append_json(link->network, &v);
580✔
1520
        if (r < 0)
580✔
1521
                return r;
1522

1523
        r = netdev_append_json(link->netdev, &v);
580✔
1524
        if (r < 0)
580✔
1525
                return r;
1526

1527
        r = device_append_json(link->dev, &v);
580✔
1528
        if (r < 0)
580✔
1529
                return r;
1530

1531
        r = dns_append_json(link, &v);
580✔
1532
        if (r < 0)
580✔
1533
                return r;
1534

1535
        r = dnr_append_json(link, &v);
580✔
1536
        if (r < 0)
580✔
1537
                return r;
1538

1539
        r = ntp_append_json(link, &v);
580✔
1540
        if (r < 0)
580✔
1541
                return r;
1542

1543
        r = sip_append_json(link, &v);
580✔
1544
        if (r < 0)
580✔
1545
                return r;
1546

1547
        r = domains_append_json(link, /* is_route = */ false, &v);
580✔
1548
        if (r < 0)
580✔
1549
                return r;
1550

1551
        r = domains_append_json(link, /* is_route = */ true, &v);
580✔
1552
        if (r < 0)
580✔
1553
                return r;
1554

1555
        r = ntas_append_json(link, &v);
580✔
1556
        if (r < 0)
580✔
1557
                return r;
1558

1559
        r = dns_misc_append_json(link, &v);
580✔
1560
        if (r < 0)
580✔
1561
                return r;
1562

1563
        r = captive_portal_append_json(link, &v);
580✔
1564
        if (r < 0)
580✔
1565
                return r;
1566

1567
        r = pref64_append_json(link, &v);
580✔
1568
        if (r < 0)
580✔
1569
                return r;
1570

1571
        r = addresses_append_json(link, /* serializing = */ false, &v);
580✔
1572
        if (r < 0)
580✔
1573
                return r;
1574

1575
        r = neighbors_append_json(link->neighbors, &v);
580✔
1576
        if (r < 0)
580✔
1577
                return r;
1578

1579
        r = nexthops_append_json(link->manager, link->ifindex, &v);
580✔
1580
        if (r < 0)
580✔
1581
                return r;
1582

1583
        r = routes_append_json(link->manager, link->ifindex, &v);
580✔
1584
        if (r < 0)
580✔
1585
                return r;
1586

1587
        r = dhcp_server_append_json(link, &v);
580✔
1588
        if (r < 0)
580✔
1589
                return r;
1590

1591
        r = dhcp_client_append_json(link, &v);
580✔
1592
        if (r < 0)
580✔
1593
                return r;
1594

1595
        r = dhcp6_client_append_json(link, &v);
580✔
1596
        if (r < 0)
580✔
1597
                return r;
1598

1599
        r = lldp_tx_append_json(link, &v);
580✔
1600
        if (r < 0)
580✔
1601
                return r;
1602

1603
        *ret = TAKE_PTR(v);
580✔
1604
        return 0;
580✔
1605
}
1606

1607
static int links_append_json(Manager *manager, sd_json_variant **v) {
78✔
1608
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
78✔
1609
        _cleanup_free_ Link **links = NULL;
78✔
1610
        size_t n_links = 0;
78✔
1611
        int r;
78✔
1612

1613
        assert(manager);
78✔
1614
        assert(v);
78✔
1615

1616
        r = hashmap_dump_sorted(manager->links_by_index, (void***) &links, &n_links);
78✔
1617
        if (r < 0)
78✔
1618
                return r;
1619

1620
        FOREACH_ARRAY(link, links, n_links) {
653✔
1621
                _cleanup_(sd_json_variant_unrefp) sd_json_variant *e = NULL;
575✔
1622

1623
                r = link_build_json(*link, &e);
575✔
1624
                if (r < 0)
575✔
1625
                        return r;
1626

1627
                r = sd_json_variant_append_array(&array, e);
575✔
1628
                if (r < 0)
575✔
1629
                        return r;
1630
        }
1631

1632
        return json_variant_set_field_non_null(v, "Interfaces", array);
78✔
1633
}
1634

1635
int manager_build_json(Manager *manager, sd_json_variant **ret) {
78✔
1636
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
78✔
1637
        int r;
78✔
1638

1639
        assert(manager);
78✔
1640
        assert(ret);
78✔
1641

1642
        r = links_append_json(manager, &v);
78✔
1643
        if (r < 0)
78✔
1644
                return r;
1645

1646
        r = nexthops_append_json(manager, /* ifindex = */ 0, &v);
78✔
1647
        if (r < 0)
78✔
1648
                return r;
1649

1650
        r = routes_append_json(manager, /* ifindex = */ 0, &v);
78✔
1651
        if (r < 0)
78✔
1652
                return r;
1653

1654
        r = routing_policy_rules_append_json(manager->rules, &v);
78✔
1655
        if (r < 0)
78✔
1656
                return r;
1657

1658
        *ret = TAKE_PTR(v);
78✔
1659
        return 0;
78✔
1660
}
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