1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include "alloc-util.h"
22 #include "bus-internal.h"
23 #include "bus-message.h"
24 #include "hexdecoct.h"
25 #include "string-util.h"
27 bool object_path_is_valid(const char *p
) {
40 for (slash
= true, q
= p
+1; *q
; q
++)
50 (*q
>= 'a' && *q
<= 'z') ||
51 (*q
>= 'A' && *q
<= 'Z') ||
52 (*q
>= '0' && *q
<= '9') ||
67 char* object_path_startswith(const char *a
, const char *b
) {
70 if (!object_path_is_valid(a
) ||
71 !object_path_is_valid(b
))
90 bool interface_name_is_valid(const char *p
) {
92 bool dot
, found_dot
= false;
97 for (dot
= true, q
= p
; *q
; q
++)
102 found_dot
= dot
= true;
107 (*q
>= 'a' && *q
<= 'z') ||
108 (*q
>= 'A' && *q
<= 'Z') ||
109 (!dot
&& *q
>= '0' && *q
<= '9') ||
130 bool service_name_is_valid(const char *p
) {
132 bool dot
, found_dot
= false, unique
;
137 unique
= p
[0] == ':';
139 for (dot
= true, q
= unique
? p
+1 : p
; *q
; q
++)
144 found_dot
= dot
= true;
149 (*q
>= 'a' && *q
<= 'z') ||
150 (*q
>= 'A' && *q
<= 'Z') ||
151 ((!dot
|| unique
) && *q
>= '0' && *q
<= '9') ||
152 IN_SET(*q
, '_', '-');
172 char* service_name_startswith(const char *a
, const char *b
) {
175 if (!service_name_is_valid(a
) ||
176 !service_name_is_valid(b
))
179 p
= startswith(a
, b
);
187 return (char*) p
+ 1;
192 bool member_name_is_valid(const char *p
) {
198 for (q
= p
; *q
; q
++) {
202 (*q
>= 'a' && *q
<= 'z') ||
203 (*q
>= 'A' && *q
<= 'Z') ||
204 (*q
>= '0' && *q
<= '9') ||
218 * Complex pattern match
219 * This checks whether @a is a 'complex-prefix' of @b, or @b is a
220 * 'complex-prefix' of @a, based on strings that consist of labels with @c as
221 * spearator. This function returns true if:
222 * - both strings are equal
223 * - either is a prefix of the other and ends with @c
224 * The second rule makes sure that either string needs to be fully included in
225 * the other, and the string which is considered the prefix needs to end with a
228 static bool complex_pattern_check(char c
, const char *a
, const char *b
) {
229 bool separator
= false;
239 return (separator
&& (*a
== 0 || *b
== 0));
250 bool namespace_complex_pattern(const char *pattern
, const char *value
) {
251 return complex_pattern_check('.', pattern
, value
);
254 bool path_complex_pattern(const char *pattern
, const char *value
) {
255 return complex_pattern_check('/', pattern
, value
);
259 * Simple pattern match
260 * This checks whether @a is a 'simple-prefix' of @b, based on strings that
261 * consist of labels with @c as separator. This function returns true, if:
262 * - if @a and @b are equal
263 * - if @a is a prefix of @b, and the first following character in @b (or the
264 * last character in @a) is @c
265 * The second rule basically makes sure that if @a is a prefix of @b, then @b
266 * must follow with a new label separated by @c. It cannot extend the label.
268 static bool simple_pattern_check(char c
, const char *a
, const char *b
) {
269 bool separator
= false;
279 return *a
== 0 && (*b
== c
|| separator
);
290 bool namespace_simple_pattern(const char *pattern
, const char *value
) {
291 return simple_pattern_check('.', pattern
, value
);
294 bool path_simple_pattern(const char *pattern
, const char *value
) {
295 return simple_pattern_check('/', pattern
, value
);
298 int bus_message_type_from_string(const char *s
, uint8_t *u
) {
299 if (streq(s
, "signal"))
300 *u
= SD_BUS_MESSAGE_SIGNAL
;
301 else if (streq(s
, "method_call"))
302 *u
= SD_BUS_MESSAGE_METHOD_CALL
;
303 else if (streq(s
, "error"))
304 *u
= SD_BUS_MESSAGE_METHOD_ERROR
;
305 else if (streq(s
, "method_return"))
306 *u
= SD_BUS_MESSAGE_METHOD_RETURN
;
313 const char *bus_message_type_to_string(uint8_t u
) {
314 if (u
== SD_BUS_MESSAGE_SIGNAL
)
316 else if (u
== SD_BUS_MESSAGE_METHOD_CALL
)
317 return "method_call";
318 else if (u
== SD_BUS_MESSAGE_METHOD_ERROR
)
320 else if (u
== SD_BUS_MESSAGE_METHOD_RETURN
)
321 return "method_return";
326 char *bus_address_escape(const char *v
) {
330 r
= new(char, strlen(v
)*3+1);
334 for (a
= v
, b
= r
; *a
; a
++) {
336 if ((*a
>= '0' && *a
<= '9') ||
337 (*a
>= 'a' && *a
<= 'z') ||
338 (*a
>= 'A' && *a
<= 'Z') ||
343 *(b
++) = hexchar(*a
>> 4);
344 *(b
++) = hexchar(*a
& 0xF);
352 int bus_maybe_reply_error(sd_bus_message
*m
, int r
, sd_bus_error
*error
) {
356 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
357 sd_bus_reply_method_errno(m
, r
, error
);
359 } else if (sd_bus_error_is_set(error
)) {
360 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
361 sd_bus_reply_method_error(m
, error
);
365 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
366 bus_message_type_to_string(m
->header
->type
),
371 strna(m
->root_container
.signature
),
372 bus_error_message(error
, r
));