Coverage Report

Created: 2026-08-08 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/systemd/src/shared/bus-message-util.c
Line
Count
Source
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3
#include <unistd.h>
4
5
#include "sd-bus.h"
6
7
#include "alloc-util.h"
8
#include "bus-message-util.h"
9
#include "bus-util.h"
10
#include "copy.h"
11
#include "in-addr-util.h"
12
#include "resolve-util.h"
13
#include "set.h"
14
#include "socket-netlink.h"
15
16
0
int bus_message_read_id128(sd_bus_message *m, sd_id128_t *ret) {
17
0
        const void *a;
18
0
        size_t sz;
19
0
        int r;
20
21
0
        assert(m);
22
23
0
        r = sd_bus_message_read_array(m, 'y', &a, &sz);
24
0
        if (r < 0)
25
0
                return r;
26
27
0
        switch (sz) {
28
29
0
        case 0:
30
0
                if (ret)
31
0
                        *ret = SD_ID128_NULL;
32
0
                return 0;
33
34
0
        case sizeof(sd_id128_t):
35
0
                if (ret)
36
0
                        memcpy(ret, a, sz);
37
0
                return !memeqzero(a, sz); /* This mimics sd_id128_is_null(), but ret may be NULL,
38
                                           * and a may be misaligned, so use memeqzero() here. */
39
40
0
        default:
41
0
                return -EINVAL;
42
0
        }
43
0
}
44
45
0
int bus_message_read_ifindex(sd_bus_message *message, sd_bus_error *reterr_error, int *ret) {
46
0
        int ifindex, r;
47
48
0
        assert(message);
49
0
        assert(ret);
50
51
0
        assert_cc(sizeof(int) == sizeof(int32_t));
52
53
0
        r = sd_bus_message_read(message, "i", &ifindex);
54
0
        if (r < 0)
55
0
                return r;
56
57
0
        if (ifindex <= 0)
58
0
                return sd_bus_error_set(reterr_error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
59
60
0
        *ret = ifindex;
61
62
0
        return 0;
63
0
}
64
65
0
int bus_message_read_family(sd_bus_message *message, sd_bus_error *reterr_error, int *ret) {
66
0
        int family, r;
67
68
0
        assert(message);
69
0
        assert(ret);
70
71
0
        assert_cc(sizeof(int) == sizeof(int32_t));
72
73
0
        r = sd_bus_message_read(message, "i", &family);
74
0
        if (r < 0)
75
0
                return r;
76
77
0
        if (!IN_SET(family, AF_INET, AF_INET6))
78
0
                return sd_bus_error_setf(reterr_error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
79
80
0
        *ret = family;
81
0
        return 0;
82
0
}
83
84
0
int bus_message_read_in_addr_auto(sd_bus_message *message, sd_bus_error *reterr_error, int *ret_family, union in_addr_union *ret_addr) {
85
0
        int family, r;
86
0
        const void *d;
87
0
        size_t sz;
88
89
0
        assert(message);
90
91
0
        r = bus_message_read_family(message, reterr_error, &family);
92
0
        if (r < 0)
93
0
                return r;
94
95
0
        r = sd_bus_message_read_array(message, 'y', &d, &sz);
96
0
        if (r < 0)
97
0
                return r;
98
99
0
        if (sz != FAMILY_ADDRESS_SIZE(family))
100
0
                return sd_bus_error_set(reterr_error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
101
102
0
        if (ret_family)
103
0
                *ret_family = family;
104
0
        if (ret_addr)
105
0
                memcpy(ret_addr, d, sz);
106
0
        return 0;
107
0
}
108
109
static int bus_message_read_dns_one(
110
                        sd_bus_message *message,
111
                        sd_bus_error *reterr_error,
112
                        bool extended,
113
                        int *ret_family,
114
                        union in_addr_union *ret_address,
115
                        uint16_t *ret_port,
116
0
                        const char **ret_server_name) {
117
0
        const char *server_name = NULL;
118
0
        union in_addr_union a;
119
0
        uint16_t port = 0;
120
0
        int family, r;
121
122
0
        assert(message);
123
0
        assert(ret_family);
124
0
        assert(ret_address);
125
0
        assert(ret_port);
126
0
        assert(ret_server_name);
127
128
0
        r = sd_bus_message_enter_container(message, 'r', extended ? "iayqs" : "iay");
129
0
        if (r <= 0)
130
0
                return r;
131
132
0
        r = bus_message_read_in_addr_auto(message, reterr_error, &family, &a);
133
0
        if (r < 0)
134
0
                return r;
135
136
0
        if (!dns_server_address_valid(family, &a)) {
137
0
                r = sd_bus_error_set(reterr_error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNS server address");
138
0
                assert(r < 0);
139
0
                return r;
140
0
        }
141
142
0
        if (extended) {
143
0
                r = sd_bus_message_read(message, "q", &port);
144
0
                if (r < 0)
145
0
                        return r;
146
147
0
                if (IN_SET(port, 53, 853))
148
0
                        port = 0;
149
150
0
                r = sd_bus_message_read(message, "s", &server_name);
151
0
                if (r < 0)
152
0
                        return r;
153
0
        }
154
155
0
        r = sd_bus_message_exit_container(message);
156
0
        if (r < 0)
157
0
                return r;
158
159
0
        *ret_family = family;
160
0
        *ret_address = a;
161
0
        *ret_port = port;
162
0
        *ret_server_name = server_name;
163
164
0
        return 1;
165
0
}
166
167
int bus_message_read_dns_servers(
168
                        sd_bus_message *message,
169
                        sd_bus_error *reterr_error,
170
                        bool extended,
171
                        struct in_addr_full ***ret_dns,
172
0
                        size_t *ret_n_dns) {
173
174
0
        struct in_addr_full **dns = NULL;
175
0
        size_t n = 0;
176
0
        int r;
177
178
0
        assert(message);
179
0
        assert(ret_dns);
180
0
        assert(ret_n_dns);
181
182
0
        r = sd_bus_message_enter_container(message, 'a', extended ? "(iayqs)" : "(iay)");
183
0
        if (r < 0)
184
0
                return r;
185
186
0
        for (;;) {
187
0
                const char *server_name;
188
0
                union in_addr_union a;
189
0
                uint16_t port;
190
0
                int family;
191
192
0
                r = bus_message_read_dns_one(message, reterr_error, extended, &family, &a, &port, &server_name);
193
0
                if (r < 0)
194
0
                        goto clear;
195
0
                if (r == 0)
196
0
                        break;
197
198
0
                if (!GREEDY_REALLOC(dns, n+1)) {
199
0
                        r = -ENOMEM;
200
0
                        goto clear;
201
0
                }
202
203
0
                r = in_addr_full_new(family, &a, port, 0, server_name, dns + n);
204
0
                if (r < 0)
205
0
                        goto clear;
206
207
0
                n++;
208
0
        }
209
210
0
        *ret_dns = TAKE_PTR(dns);
211
0
        *ret_n_dns = n;
212
0
        return 0;
213
214
0
clear:
215
0
        for (size_t i = 0; i < n; i++)
216
0
                in_addr_full_free(dns[i]);
217
0
        free(dns);
218
219
0
        return r;
220
0
}
221
222
0
int bus_message_append_string_set(sd_bus_message *m, const Set *set) {
223
0
        int r;
224
225
0
        assert(m);
226
227
0
        r = sd_bus_message_open_container(m, 'a', "s");
228
0
        if (r < 0)
229
0
                return r;
230
231
0
        const char *s;
232
0
        SET_FOREACH(s, set) {
233
0
                r = sd_bus_message_append(m, "s", s);
234
0
                if (r < 0)
235
0
                        return r;
236
0
        }
237
238
0
        return sd_bus_message_close_container(m);
239
0
}
240
241
0
int bus_message_dump_string(sd_bus_message *message) {
242
0
        const char *s;
243
0
        int r;
244
245
0
        assert(message);
246
247
0
        r = sd_bus_message_read(message, "s", &s);
248
0
        if (r < 0)
249
0
                return bus_log_parse_error(r);
250
251
0
        fputs(s, stdout);
252
0
        return 0;
253
0
}
254
255
0
int bus_message_dump_fd(sd_bus_message *message) {
256
0
        int fd, r;
257
258
0
        assert(message);
259
260
0
        r = sd_bus_message_read(message, "h", &fd);
261
0
        if (r < 0)
262
0
                return bus_log_parse_error(r);
263
264
0
        fflush(stdout);
265
0
        r = copy_bytes(fd, STDOUT_FILENO, UINT64_MAX, 0);
266
0
        if (r < 0)
267
0
                return log_error_errno(r, "Failed to dump contents in received file descriptor: %m");
268
269
0
        return 0;
270
0
}
271
272
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(bus_message_hash_ops,
273
                                      void, trivial_hash_func, trivial_compare_func,
274
                                      sd_bus_message, sd_bus_message_unref);