]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/bus-internal.c
Revert "sd-bus: do not connect to dbus-1 socket when kdbus is available"
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-internal.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "bus-message.h"
23 #include "bus-internal.h"
24
25 bool object_path_is_valid(const char *p) {
26 const char *q;
27 bool slash;
28
29 if (!p)
30 return false;
31
32 if (p[0] != '/')
33 return false;
34
35 if (p[1] == 0)
36 return true;
37
38 for (slash = true, q = p+1; *q; q++)
39 if (*q == '/') {
40 if (slash)
41 return false;
42
43 slash = true;
44 } else {
45 bool good;
46
47 good =
48 (*q >= 'a' && *q <= 'z') ||
49 (*q >= 'A' && *q <= 'Z') ||
50 (*q >= '0' && *q <= '9') ||
51 *q == '_';
52
53 if (!good)
54 return false;
55
56 slash = false;
57 }
58
59 if (slash)
60 return false;
61
62 return true;
63 }
64
65 char* object_path_startswith(const char *a, const char *b) {
66 const char *p;
67
68 if (!object_path_is_valid(a) ||
69 !object_path_is_valid(b))
70 return NULL;
71
72 if (streq(b, "/"))
73 return (char*) a + 1;
74
75 p = startswith(a, b);
76 if (!p)
77 return NULL;
78
79 if (*p == 0)
80 return (char*) p;
81
82 if (*p == '/')
83 return (char*) p + 1;
84
85 return NULL;
86 }
87
88 bool interface_name_is_valid(const char *p) {
89 const char *q;
90 bool dot, found_dot = false;
91
92 if (isempty(p))
93 return false;
94
95 for (dot = true, q = p; *q; q++)
96 if (*q == '.') {
97 if (dot)
98 return false;
99
100 found_dot = dot = true;
101 } else {
102 bool good;
103
104 good =
105 (*q >= 'a' && *q <= 'z') ||
106 (*q >= 'A' && *q <= 'Z') ||
107 (!dot && *q >= '0' && *q <= '9') ||
108 *q == '_';
109
110 if (!good)
111 return false;
112
113 dot = false;
114 }
115
116 if (q - p > 255)
117 return false;
118
119 if (dot)
120 return false;
121
122 if (!found_dot)
123 return false;
124
125 return true;
126 }
127
128 bool service_name_is_valid(const char *p) {
129 const char *q;
130 bool dot, found_dot = false, unique;
131
132 if (isempty(p))
133 return false;
134
135 unique = p[0] == ':';
136
137 for (dot = true, q = unique ? p+1 : p; *q; q++)
138 if (*q == '.') {
139 if (dot)
140 return false;
141
142 found_dot = dot = true;
143 } else {
144 bool good;
145
146 good =
147 (*q >= 'a' && *q <= 'z') ||
148 (*q >= 'A' && *q <= 'Z') ||
149 ((!dot || unique) && *q >= '0' && *q <= '9') ||
150 *q == '_' || *q == '-';
151
152 if (!good)
153 return false;
154
155 dot = false;
156 }
157
158 if (q - p > 255)
159 return false;
160
161 if (dot)
162 return false;
163
164 if (!found_dot)
165 return false;
166
167 return true;
168 }
169
170 char* service_name_startswith(const char *a, const char *b) {
171 const char *p;
172
173 if (!service_name_is_valid(a) ||
174 !service_name_is_valid(b))
175 return NULL;
176
177 p = startswith(a, b);
178 if (!p)
179 return NULL;
180
181 if (*p == 0)
182 return (char*) p;
183
184 if (*p == '.')
185 return (char*) p + 1;
186
187 return NULL;
188 }
189
190 bool member_name_is_valid(const char *p) {
191 const char *q;
192
193 if (isempty(p))
194 return false;
195
196 for (q = p; *q; q++) {
197 bool good;
198
199 good =
200 (*q >= 'a' && *q <= 'z') ||
201 (*q >= 'A' && *q <= 'Z') ||
202 (*q >= '0' && *q <= '9') ||
203 *q == '_';
204
205 if (!good)
206 return false;
207 }
208
209 if (q - p > 255)
210 return false;
211
212 return true;
213 }
214
215 /*
216 * Complex pattern match
217 * This checks whether @a is a 'complex-prefix' of @b, or @b is a
218 * 'complex-prefix' of @a, based on strings that consist of labels with @c as
219 * spearator. This function returns true if:
220 * - both strings are equal
221 * - either is a prefix of the other and ends with @c
222 * The second rule makes sure that either string needs to be fully included in
223 * the other, and the string which is considered the prefix needs to end with a
224 * separator.
225 */
226 static bool complex_pattern_check(char c, const char *a, const char *b) {
227 bool separator = false;
228
229 if (!a && !b)
230 return true;
231
232 if (!a || !b)
233 return false;
234
235 for (;;) {
236 if (*a != *b)
237 return (separator && (*a == 0 || *b == 0));
238
239 if (*a == 0)
240 return true;
241
242 separator = *a == c;
243
244 a++, b++;
245 }
246 }
247
248 bool namespace_complex_pattern(const char *pattern, const char *value) {
249 return complex_pattern_check('.', pattern, value);
250 }
251
252 bool path_complex_pattern(const char *pattern, const char *value) {
253 return complex_pattern_check('/', pattern, value);
254 }
255
256 /*
257 * Simple pattern match
258 * This checks whether @a is a 'simple-prefix' of @b, based on strings that
259 * consist of labels with @c as separator. This function returns true, if:
260 * - if @a and @b are equal
261 * - if @a is a prefix of @b, and the first following character in @b (or the
262 * last character in @a) is @c
263 * The second rule basically makes sure that if @a is a prefix of @b, then @b
264 * must follow with a new label separated by @c. It cannot extend the label.
265 */
266 static bool simple_pattern_check(char c, const char *a, const char *b) {
267 bool separator = false;
268
269 if (!a && !b)
270 return true;
271
272 if (!a || !b)
273 return false;
274
275 for (;;) {
276 if (*a != *b)
277 return *a == 0 && (*b == c || separator);
278
279 if (*a == 0)
280 return true;
281
282 separator = *a == c;
283
284 a++, b++;
285 }
286 }
287
288 bool namespace_simple_pattern(const char *pattern, const char *value) {
289 return simple_pattern_check('.', pattern, value);
290 }
291
292 bool path_simple_pattern(const char *pattern, const char *value) {
293 return simple_pattern_check('/', pattern, value);
294 }
295
296 int bus_message_type_from_string(const char *s, uint8_t *u) {
297 if (streq(s, "signal"))
298 *u = SD_BUS_MESSAGE_SIGNAL;
299 else if (streq(s, "method_call"))
300 *u = SD_BUS_MESSAGE_METHOD_CALL;
301 else if (streq(s, "error"))
302 *u = SD_BUS_MESSAGE_METHOD_ERROR;
303 else if (streq(s, "method_return"))
304 *u = SD_BUS_MESSAGE_METHOD_RETURN;
305 else
306 return -EINVAL;
307
308 return 0;
309 }
310
311 const char *bus_message_type_to_string(uint8_t u) {
312 if (u == SD_BUS_MESSAGE_SIGNAL)
313 return "signal";
314 else if (u == SD_BUS_MESSAGE_METHOD_CALL)
315 return "method_call";
316 else if (u == SD_BUS_MESSAGE_METHOD_ERROR)
317 return "error";
318 else if (u == SD_BUS_MESSAGE_METHOD_RETURN)
319 return "method_return";
320 else
321 return NULL;
322 }
323
324 char *bus_address_escape(const char *v) {
325 const char *a;
326 char *r, *b;
327
328 r = new(char, strlen(v)*3+1);
329 if (!r)
330 return NULL;
331
332 for (a = v, b = r; *a; a++) {
333
334 if ((*a >= '0' && *a <= '9') ||
335 (*a >= 'a' && *a <= 'z') ||
336 (*a >= 'A' && *a <= 'Z') ||
337 strchr("_-/.", *a))
338 *(b++) = *a;
339 else {
340 *(b++) = '%';
341 *(b++) = hexchar(*a >> 4);
342 *(b++) = hexchar(*a & 0xF);
343 }
344 }
345
346 *b = 0;
347 return r;
348 }
349
350 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
351 assert(m);
352
353 if (r < 0) {
354 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
355 sd_bus_reply_method_errno(m, r, error);
356
357 } else if (sd_bus_error_is_set(error)) {
358 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
359 sd_bus_reply_method_error(m, error);
360 } else
361 return r;
362
363 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
364 bus_message_type_to_string(m->header->type),
365 strna(m->sender),
366 strna(m->path),
367 strna(m->interface),
368 strna(m->member),
369 strna(m->root_container.signature),
370 bus_error_message(error, r));
371
372 return 1;
373 }