2017-11-18 17:09:20 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
2013-03-19 20:03:16 +01:00
|
|
|
/***
|
|
|
|
This file is part of systemd.
|
|
|
|
|
|
|
|
Copyright 2013 Lennart Poettering
|
|
|
|
|
|
|
|
systemd is free software; you can redistribute it and/or modify it
|
|
|
|
under the terms of the GNU Lesser General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2.1 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
systemd is distributed in the hope that it will be useful, but
|
|
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
|
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
***/
|
|
|
|
|
2017-10-03 10:41:51 +02:00
|
|
|
#if HAVE_VALGRIND_MEMCHECK_H
|
2013-04-14 03:19:51 +02:00
|
|
|
#include <valgrind/memcheck.h>
|
|
|
|
#endif
|
|
|
|
|
2013-03-19 20:03:16 +01:00
|
|
|
#include <errno.h>
|
2015-11-16 22:09:36 +01:00
|
|
|
#include <stddef.h>
|
2013-03-19 20:03:16 +01:00
|
|
|
|
|
|
|
#include "sd-bus.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
#include "alloc-util.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "bus-bloom.h"
|
2015-10-27 00:42:07 +01:00
|
|
|
#include "bus-control.h"
|
2013-03-19 20:03:16 +01:00
|
|
|
#include "bus-internal.h"
|
|
|
|
#include "bus-message.h"
|
2015-08-27 16:32:22 +02:00
|
|
|
#include "bus-util.h"
|
2015-10-26 23:32:16 +01:00
|
|
|
#include "capability-util.h"
|
2015-10-27 01:26:31 +01:00
|
|
|
#include "stdio-util.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "string-util.h"
|
|
|
|
#include "strv.h"
|
2015-10-27 00:42:07 +01:00
|
|
|
#include "user-util.h"
|
2013-03-19 20:03:16 +01:00
|
|
|
|
2013-11-06 08:33:42 +01:00
|
|
|
_public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
|
2013-03-22 03:34:29 +01:00
|
|
|
int r;
|
|
|
|
|
2013-11-29 17:57:00 +01:00
|
|
|
assert_return(bus, -EINVAL);
|
|
|
|
assert_return(unique, -EINVAL);
|
|
|
|
assert_return(!bus_pid_changed(bus), -ECHILD);
|
2013-03-22 03:34:29 +01:00
|
|
|
|
2015-04-23 16:23:15 +02:00
|
|
|
if (!bus->bus_client)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2013-03-22 03:34:29 +01:00
|
|
|
r = bus_ensure_running(bus);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-03-19 20:03:16 +01:00
|
|
|
|
2013-03-22 03:34:29 +01:00
|
|
|
*unique = bus->unique_name;
|
|
|
|
return 0;
|
2013-03-19 20:03:16 +01:00
|
|
|
}
|
|
|
|
|
2017-12-18 20:10:13 +01:00
|
|
|
static int validate_request_name_parameters(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *name,
|
|
|
|
uint64_t flags,
|
|
|
|
uint32_t *ret_param) {
|
|
|
|
|
|
|
|
uint32_t param = 0;
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(name);
|
|
|
|
assert(ret_param);
|
2013-03-19 20:03:16 +01:00
|
|
|
|
2017-12-18 14:48:16 +01:00
|
|
|
assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
|
|
|
|
assert_return(service_name_is_valid(name), -EINVAL);
|
|
|
|
assert_return(name[0] != ':', -EINVAL);
|
|
|
|
|
|
|
|
if (!bus->bus_client)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
/* Don't allow requesting the special driver and local names */
|
|
|
|
if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (!BUS_IS_OPEN(bus->state))
|
|
|
|
return -ENOTCONN;
|
2013-12-03 18:01:26 +01:00
|
|
|
|
2013-12-12 05:55:58 +01:00
|
|
|
if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
|
|
|
|
param |= BUS_NAME_ALLOW_REPLACEMENT;
|
|
|
|
if (flags & SD_BUS_NAME_REPLACE_EXISTING)
|
|
|
|
param |= BUS_NAME_REPLACE_EXISTING;
|
|
|
|
if (!(flags & SD_BUS_NAME_QUEUE))
|
|
|
|
param |= BUS_NAME_DO_NOT_QUEUE;
|
|
|
|
|
2017-12-18 20:10:13 +01:00
|
|
|
*ret_param = param;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
_public_ int sd_bus_request_name(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *name,
|
|
|
|
uint64_t flags) {
|
|
|
|
|
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
|
|
|
uint32_t ret, param = 0;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert_return(bus, -EINVAL);
|
|
|
|
assert_return(name, -EINVAL);
|
|
|
|
assert_return(!bus_pid_changed(bus), -ECHILD);
|
|
|
|
|
|
|
|
r = validate_request_name_parameters(bus, name, flags, ¶m);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2013-12-03 18:01:26 +01:00
|
|
|
r = sd_bus_call_method(
|
|
|
|
bus,
|
|
|
|
"org.freedesktop.DBus",
|
2013-12-23 03:30:41 +01:00
|
|
|
"/org/freedesktop/DBus",
|
2013-12-03 18:01:26 +01:00
|
|
|
"org.freedesktop.DBus",
|
|
|
|
"RequestName",
|
|
|
|
NULL,
|
|
|
|
&reply,
|
|
|
|
"su",
|
|
|
|
name,
|
2013-12-12 05:55:58 +01:00
|
|
|
param);
|
2013-12-03 18:01:26 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(reply, "u", &ret);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2017-12-18 20:10:13 +01:00
|
|
|
switch (ret) {
|
|
|
|
|
|
|
|
case BUS_NAME_ALREADY_OWNER:
|
2013-12-03 18:01:26 +01:00
|
|
|
return -EALREADY;
|
2017-12-18 20:10:13 +01:00
|
|
|
|
|
|
|
case BUS_NAME_EXISTS:
|
2013-12-03 18:01:26 +01:00
|
|
|
return -EEXIST;
|
2017-12-18 20:10:13 +01:00
|
|
|
|
|
|
|
case BUS_NAME_IN_QUEUE:
|
2013-12-03 18:01:26 +01:00
|
|
|
return 0;
|
2017-12-18 20:10:13 +01:00
|
|
|
|
|
|
|
case BUS_NAME_PRIMARY_OWNER:
|
2013-12-03 20:31:34 +01:00
|
|
|
return 1;
|
2017-12-18 20:10:13 +01:00
|
|
|
}
|
2013-12-03 18:01:26 +01:00
|
|
|
|
2013-12-03 20:31:34 +01:00
|
|
|
return -EIO;
|
2013-12-03 18:01:26 +01:00
|
|
|
}
|
|
|
|
|
2017-12-18 20:10:13 +01:00
|
|
|
static int default_request_name_handler(
|
|
|
|
sd_bus_message *m,
|
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *ret_error) {
|
|
|
|
|
2017-12-18 14:48:16 +01:00
|
|
|
uint32_t ret;
|
|
|
|
int r;
|
|
|
|
|
2017-12-18 20:10:13 +01:00
|
|
|
assert(m);
|
|
|
|
|
|
|
|
if (sd_bus_message_is_method_error(m, NULL)) {
|
|
|
|
log_debug_errno(sd_bus_message_get_errno(m),
|
|
|
|
"Unable to request name, failing connection: %s",
|
|
|
|
sd_bus_message_get_error(m)->message);
|
|
|
|
|
|
|
|
bus_enter_closing(sd_bus_message_get_bus(m));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = sd_bus_message_read(m, "u", &ret);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
switch (ret) {
|
|
|
|
|
|
|
|
case BUS_NAME_ALREADY_OWNER:
|
|
|
|
log_debug("Already owner of requested service name, ignoring.");
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
case BUS_NAME_IN_QUEUE:
|
|
|
|
log_debug("In queue for requested service name.");
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
case BUS_NAME_PRIMARY_OWNER:
|
|
|
|
log_debug("Successfully acquired requested service name.");
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
case BUS_NAME_EXISTS:
|
|
|
|
log_debug("Requested service name already owned, failing connection.");
|
|
|
|
bus_enter_closing(sd_bus_message_get_bus(m));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
log_debug("Unexpected response from RequestName(), failing connection.");
|
|
|
|
bus_enter_closing(sd_bus_message_get_bus(m));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
_public_ int sd_bus_request_name_async(
|
|
|
|
sd_bus *bus,
|
|
|
|
sd_bus_slot **ret_slot,
|
|
|
|
const char *name,
|
|
|
|
uint64_t flags,
|
|
|
|
sd_bus_message_handler_t callback,
|
|
|
|
void *userdata) {
|
|
|
|
|
|
|
|
uint32_t param = 0;
|
|
|
|
int r;
|
|
|
|
|
2013-11-29 17:57:00 +01:00
|
|
|
assert_return(bus, -EINVAL);
|
|
|
|
assert_return(name, -EINVAL);
|
|
|
|
assert_return(!bus_pid_changed(bus), -ECHILD);
|
2017-12-18 20:10:13 +01:00
|
|
|
|
|
|
|
r = validate_request_name_parameters(bus, name, flags, ¶m);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
return sd_bus_call_method_async(
|
|
|
|
bus,
|
|
|
|
ret_slot,
|
|
|
|
"org.freedesktop.DBus",
|
|
|
|
"/org/freedesktop/DBus",
|
|
|
|
"org.freedesktop.DBus",
|
|
|
|
"RequestName",
|
|
|
|
callback ?: default_request_name_handler,
|
|
|
|
userdata,
|
|
|
|
"su",
|
|
|
|
name,
|
|
|
|
param);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int validate_release_name_parameters(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *name) {
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(name);
|
|
|
|
|
2013-12-18 02:23:07 +01:00
|
|
|
assert_return(service_name_is_valid(name), -EINVAL);
|
|
|
|
assert_return(name[0] != ':', -EINVAL);
|
2013-03-19 20:03:16 +01:00
|
|
|
|
2015-04-23 16:23:15 +02:00
|
|
|
if (!bus->bus_client)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2017-12-18 14:48:16 +01:00
|
|
|
/* Don't allow releasing the special driver and local names */
|
2015-01-07 19:29:14 +01:00
|
|
|
if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
|
|
|
|
return -EINVAL;
|
|
|
|
|
2014-03-19 21:41:21 +01:00
|
|
|
if (!BUS_IS_OPEN(bus->state))
|
|
|
|
return -ENOTCONN;
|
|
|
|
|
2017-12-18 20:10:13 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
_public_ int sd_bus_release_name(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *name) {
|
|
|
|
|
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
|
|
|
uint32_t ret;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert_return(bus, -EINVAL);
|
|
|
|
assert_return(name, -EINVAL);
|
|
|
|
assert_return(!bus_pid_changed(bus), -ECHILD);
|
|
|
|
|
|
|
|
r = validate_release_name_parameters(bus, name);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2013-12-03 18:01:26 +01:00
|
|
|
r = sd_bus_call_method(
|
|
|
|
bus,
|
|
|
|
"org.freedesktop.DBus",
|
2013-12-23 03:30:41 +01:00
|
|
|
"/org/freedesktop/DBus",
|
2013-12-03 18:01:26 +01:00
|
|
|
"org.freedesktop.DBus",
|
|
|
|
"ReleaseName",
|
|
|
|
NULL,
|
|
|
|
&reply,
|
|
|
|
"s",
|
|
|
|
name);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(reply, "u", &ret);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2017-12-18 20:10:13 +01:00
|
|
|
|
|
|
|
switch (ret) {
|
|
|
|
|
|
|
|
case BUS_NAME_NON_EXISTENT:
|
2013-12-13 12:12:24 +01:00
|
|
|
return -ESRCH;
|
2017-12-18 20:10:13 +01:00
|
|
|
|
|
|
|
case BUS_NAME_NOT_OWNER:
|
2013-12-13 12:12:24 +01:00
|
|
|
return -EADDRINUSE;
|
2017-12-18 20:10:13 +01:00
|
|
|
|
|
|
|
case BUS_NAME_RELEASED:
|
2013-12-03 18:01:26 +01:00
|
|
|
return 0;
|
2017-12-18 20:10:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int default_release_name_handler(
|
|
|
|
sd_bus_message *m,
|
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *ret_error) {
|
|
|
|
|
|
|
|
uint32_t ret;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(m);
|
|
|
|
|
|
|
|
if (sd_bus_message_is_method_error(m, NULL)) {
|
|
|
|
log_debug_errno(sd_bus_message_get_errno(m),
|
|
|
|
"Unable to release name, failing connection: %s",
|
|
|
|
sd_bus_message_get_error(m)->message);
|
2013-12-03 18:01:26 +01:00
|
|
|
|
2017-12-18 20:10:13 +01:00
|
|
|
bus_enter_closing(sd_bus_message_get_bus(m));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = sd_bus_message_read(m, "u", &ret);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
switch (ret) {
|
|
|
|
|
|
|
|
case BUS_NAME_NON_EXISTENT:
|
|
|
|
log_debug("Name asked to release is not taken currently, ignoring.");
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
case BUS_NAME_NOT_OWNER:
|
|
|
|
log_debug("Name asked to release is owned by somebody else, ignoring.");
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
case BUS_NAME_RELEASED:
|
|
|
|
log_debug("Name successfully released.");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
log_debug("Unexpected response from ReleaseName(), failing connection.");
|
|
|
|
bus_enter_closing(sd_bus_message_get_bus(m));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
_public_ int sd_bus_release_name_async(
|
|
|
|
sd_bus *bus,
|
|
|
|
sd_bus_slot **ret_slot,
|
|
|
|
const char *name,
|
|
|
|
sd_bus_message_handler_t callback,
|
|
|
|
void *userdata) {
|
|
|
|
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert_return(bus, -EINVAL);
|
|
|
|
assert_return(name, -EINVAL);
|
|
|
|
assert_return(!bus_pid_changed(bus), -ECHILD);
|
|
|
|
|
|
|
|
r = validate_release_name_parameters(bus, name);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
return sd_bus_call_method_async(
|
|
|
|
bus,
|
|
|
|
ret_slot,
|
|
|
|
"org.freedesktop.DBus",
|
|
|
|
"/org/freedesktop/DBus",
|
|
|
|
"org.freedesktop.DBus",
|
|
|
|
"ReleaseName",
|
|
|
|
callback ?: default_release_name_handler,
|
|
|
|
userdata,
|
|
|
|
"s",
|
|
|
|
name);
|
2013-12-03 18:01:26 +01:00
|
|
|
}
|
|
|
|
|
2017-12-18 14:48:16 +01:00
|
|
|
_public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
|
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
|
|
|
_cleanup_strv_free_ char **x = NULL, **y = NULL;
|
|
|
|
int r;
|
|
|
|
|
2013-11-29 17:57:00 +01:00
|
|
|
assert_return(bus, -EINVAL);
|
2017-12-18 14:48:16 +01:00
|
|
|
assert_return(acquired || activatable, -EINVAL);
|
2013-11-29 17:57:00 +01:00
|
|
|
assert_return(!bus_pid_changed(bus), -ECHILD);
|
2013-03-19 20:03:16 +01:00
|
|
|
|
2015-04-23 16:23:15 +02:00
|
|
|
if (!bus->bus_client)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2014-03-19 21:41:21 +01:00
|
|
|
if (!BUS_IS_OPEN(bus->state))
|
|
|
|
return -ENOTCONN;
|
|
|
|
|
2013-12-03 18:42:51 +01:00
|
|
|
if (acquired) {
|
|
|
|
r = sd_bus_call_method(
|
|
|
|
bus,
|
|
|
|
"org.freedesktop.DBus",
|
2013-12-23 03:30:41 +01:00
|
|
|
"/org/freedesktop/DBus",
|
2013-12-03 18:42:51 +01:00
|
|
|
"org.freedesktop.DBus",
|
|
|
|
"ListNames",
|
|
|
|
NULL,
|
|
|
|
&reply,
|
|
|
|
NULL);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = sd_bus_message_read_strv(reply, &x);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
reply = sd_bus_message_unref(reply);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (activatable) {
|
|
|
|
r = sd_bus_call_method(
|
|
|
|
bus,
|
|
|
|
"org.freedesktop.DBus",
|
2013-12-23 03:30:41 +01:00
|
|
|
"/org/freedesktop/DBus",
|
2013-12-03 18:42:51 +01:00
|
|
|
"org.freedesktop.DBus",
|
|
|
|
"ListActivatableNames",
|
|
|
|
NULL,
|
|
|
|
&reply,
|
|
|
|
NULL);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = sd_bus_message_read_strv(reply, &y);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
*activatable = y;
|
|
|
|
y = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (acquired) {
|
|
|
|
*acquired = x;
|
|
|
|
x = NULL;
|
2013-11-28 20:41:55 +01:00
|
|
|
}
|
2013-03-19 20:03:16 +01:00
|
|
|
|
2013-11-30 04:14:10 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-12-18 14:48:16 +01:00
|
|
|
_public_ int sd_bus_get_name_creds(
|
2013-12-03 18:01:26 +01:00
|
|
|
sd_bus *bus,
|
|
|
|
const char *name,
|
|
|
|
uint64_t mask,
|
|
|
|
sd_bus_creds **creds) {
|
|
|
|
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL;
|
|
|
|
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
|
2013-12-03 18:01:26 +01:00
|
|
|
const char *unique = NULL;
|
|
|
|
pid_t pid = 0;
|
|
|
|
int r;
|
|
|
|
|
2017-12-18 14:48:16 +01:00
|
|
|
assert_return(bus, -EINVAL);
|
|
|
|
assert_return(name, -EINVAL);
|
|
|
|
assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
|
|
|
|
assert_return(mask == 0 || creds, -EINVAL);
|
|
|
|
assert_return(!bus_pid_changed(bus), -ECHILD);
|
|
|
|
assert_return(service_name_is_valid(name), -EINVAL);
|
|
|
|
|
|
|
|
if (!bus->bus_client)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
/* Turn off augmenting if this isn't a local connection. If the connection is not local, then /proc is not
|
|
|
|
* going to match. */
|
|
|
|
if (!bus->is_local)
|
|
|
|
mask &= ~SD_BUS_CREDS_AUGMENT;
|
|
|
|
|
|
|
|
if (streq(name, "org.freedesktop.DBus.Local"))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (streq(name, "org.freedesktop.DBus"))
|
|
|
|
return sd_bus_get_owner_creds(bus, mask, creds);
|
|
|
|
|
|
|
|
if (!BUS_IS_OPEN(bus->state))
|
|
|
|
return -ENOTCONN;
|
|
|
|
|
2013-12-03 18:01:26 +01:00
|
|
|
/* Only query the owner if the caller wants to know it or if
|
|
|
|
* the caller just wants to check whether a name exists */
|
|
|
|
if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
|
|
|
|
r = sd_bus_call_method(
|
|
|
|
bus,
|
|
|
|
"org.freedesktop.DBus",
|
2013-12-23 03:30:41 +01:00
|
|
|
"/org/freedesktop/DBus",
|
2013-12-03 18:01:26 +01:00
|
|
|
"org.freedesktop.DBus",
|
|
|
|
"GetNameOwner",
|
|
|
|
NULL,
|
|
|
|
&reply_unique,
|
|
|
|
"s",
|
|
|
|
name);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(reply_unique, "s", &unique);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mask != 0) {
|
2017-06-26 18:52:47 +02:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
|
|
|
bool need_pid, need_uid, need_selinux, need_separate_calls;
|
2013-12-03 18:01:26 +01:00
|
|
|
c = bus_creds_new();
|
|
|
|
if (!c)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
|
|
|
|
c->unique_name = strdup(unique);
|
|
|
|
if (!c->unique_name)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
|
|
|
|
}
|
2013-11-30 04:14:10 +01:00
|
|
|
|
2017-06-26 18:52:47 +02:00
|
|
|
need_pid = (mask & SD_BUS_CREDS_PID) ||
|
|
|
|
((mask & SD_BUS_CREDS_AUGMENT) &&
|
|
|
|
(mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
|
|
|
|
SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
|
|
|
|
SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
|
|
|
|
SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
|
|
|
|
SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
|
|
|
|
SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
|
|
|
|
SD_BUS_CREDS_SELINUX_CONTEXT|
|
|
|
|
SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)));
|
|
|
|
need_uid = mask & SD_BUS_CREDS_EUID;
|
|
|
|
need_selinux = mask & SD_BUS_CREDS_SELINUX_CONTEXT;
|
sd-bus: update to current kernel version, by splitting off the extended KDBUS_ITEM_PIDS structure from KDBUS_ITEM_CREDS
Also:
- adds support for euid, suid, fsuid, egid, sgid, fsgid fields.
- makes augmentation of creds with data from /proc explicitly
controllable to give apps better control over this, given that this is
racy.
- enables augmentation for kdbus connections (previously we only did it
for dbus1). This is useful since with recent kdbus versions it is
possible for clients to control the metadata they want to send.
- changes sd_bus_query_sender_privilege() to take the euid of the client
into consideration, if known
- when we don't have permissions to read augmentation data from /proc,
don't fail, just don't add the data in
2014-11-24 21:41:40 +01:00
|
|
|
|
2017-06-26 18:52:47 +02:00
|
|
|
if (need_pid + need_uid + need_selinux > 1) {
|
|
|
|
|
|
|
|
/* If we need more than one of the credentials, then use GetConnectionCredentials() */
|
2013-11-30 04:14:10 +01:00
|
|
|
|
2013-12-03 18:01:26 +01:00
|
|
|
r = sd_bus_call_method(
|
|
|
|
bus,
|
|
|
|
"org.freedesktop.DBus",
|
2013-12-23 03:30:41 +01:00
|
|
|
"/org/freedesktop/DBus",
|
2013-12-03 18:01:26 +01:00
|
|
|
"org.freedesktop.DBus",
|
2017-06-26 18:52:47 +02:00
|
|
|
"GetConnectionCredentials",
|
|
|
|
&error,
|
2013-12-03 18:01:26 +01:00
|
|
|
&reply,
|
|
|
|
"s",
|
2017-06-26 18:52:47 +02:00
|
|
|
unique ?: name);
|
2013-11-30 04:14:10 +01:00
|
|
|
|
2017-06-26 18:52:47 +02:00
|
|
|
if (r < 0) {
|
2013-12-03 18:01:26 +01:00
|
|
|
|
2017-06-26 18:52:47 +02:00
|
|
|
if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
|
|
|
|
return r;
|
2013-11-30 04:14:10 +01:00
|
|
|
|
2017-06-26 18:52:47 +02:00
|
|
|
/* If we got an unknown method error, fall back to the invidual calls... */
|
|
|
|
need_separate_calls = true;
|
|
|
|
sd_bus_error_free(&error);
|
2013-11-30 04:14:10 +01:00
|
|
|
|
2017-06-26 18:52:47 +02:00
|
|
|
} else {
|
|
|
|
need_separate_calls = false;
|
2013-11-30 04:14:10 +01:00
|
|
|
|
2017-06-26 18:52:47 +02:00
|
|
|
r = sd_bus_message_enter_container(reply, 'a', "{sv}");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-11-30 04:14:10 +01:00
|
|
|
|
2017-06-26 18:52:47 +02:00
|
|
|
for (;;) {
|
|
|
|
const char *m;
|
2013-11-30 04:14:10 +01:00
|
|
|
|
2017-06-26 18:52:47 +02:00
|
|
|
r = sd_bus_message_enter_container(reply, 'e', "sv");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
if (r == 0)
|
|
|
|
break;
|
2013-11-30 04:14:10 +01:00
|
|
|
|
2017-06-26 18:52:47 +02:00
|
|
|
r = sd_bus_message_read(reply, "s", &m);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-11-30 04:14:10 +01:00
|
|
|
|
2017-06-26 18:52:47 +02:00
|
|
|
if (need_uid && streq(m, "UnixUserID")) {
|
|
|
|
uint32_t u;
|
2013-11-30 04:14:10 +01:00
|
|
|
|
2017-06-26 18:52:47 +02:00
|
|
|
r = sd_bus_message_read(reply, "v", "u", &u);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
c->euid = u;
|
|
|
|
c->mask |= SD_BUS_CREDS_EUID;
|
|
|
|
|
|
|
|
} else if (need_pid && streq(m, "ProcessID")) {
|
|
|
|
uint32_t p;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(reply, "v", "u", &p);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
pid = p;
|
|
|
|
if (mask & SD_BUS_CREDS_PID) {
|
|
|
|
c->pid = p;
|
|
|
|
c->mask |= SD_BUS_CREDS_PID;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (need_selinux && streq(m, "LinuxSecurityLabel")) {
|
|
|
|
const void *p = NULL;
|
|
|
|
size_t sz = 0;
|
|
|
|
|
|
|
|
r = sd_bus_message_enter_container(reply, 'v', "ay");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = sd_bus_message_read_array(reply, 'y', &p, &sz);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
free(c->label);
|
|
|
|
c->label = strndup(p, sz);
|
|
|
|
if (!c->label)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
|
|
|
|
|
|
|
|
r = sd_bus_message_exit_container(reply);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
} else {
|
|
|
|
r = sd_bus_message_skip(reply, "v");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = sd_bus_message_exit_container(reply);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = sd_bus_message_exit_container(reply);
|
|
|
|
if (r < 0)
|
2014-11-24 22:11:53 +01:00
|
|
|
return r;
|
2017-06-26 18:52:47 +02:00
|
|
|
|
|
|
|
if (need_pid && pid == 0)
|
|
|
|
return -EPROTO;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else /* When we only need a single field, then let's use separate calls */
|
|
|
|
need_separate_calls = true;
|
|
|
|
|
|
|
|
if (need_separate_calls) {
|
|
|
|
if (need_pid) {
|
|
|
|
uint32_t u;
|
|
|
|
|
|
|
|
r = sd_bus_call_method(
|
|
|
|
bus,
|
|
|
|
"org.freedesktop.DBus",
|
|
|
|
"/org/freedesktop/DBus",
|
|
|
|
"org.freedesktop.DBus",
|
|
|
|
"GetConnectionUnixProcessID",
|
|
|
|
NULL,
|
|
|
|
&reply,
|
|
|
|
"s",
|
|
|
|
unique ?: name);
|
2014-11-24 22:11:53 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-12-03 18:01:26 +01:00
|
|
|
|
2017-06-26 18:52:47 +02:00
|
|
|
r = sd_bus_message_read(reply, "u", &u);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-12-03 18:01:26 +01:00
|
|
|
|
2017-06-26 18:52:47 +02:00
|
|
|
pid = u;
|
|
|
|
if (mask & SD_BUS_CREDS_PID) {
|
|
|
|
c->pid = u;
|
|
|
|
c->mask |= SD_BUS_CREDS_PID;
|
|
|
|
}
|
|
|
|
|
|
|
|
reply = sd_bus_message_unref(reply);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (need_uid) {
|
|
|
|
uint32_t u;
|
|
|
|
|
|
|
|
r = sd_bus_call_method(
|
|
|
|
bus,
|
|
|
|
"org.freedesktop.DBus",
|
|
|
|
"/org/freedesktop/DBus",
|
|
|
|
"org.freedesktop.DBus",
|
|
|
|
"GetConnectionUnixUser",
|
|
|
|
NULL,
|
|
|
|
&reply,
|
|
|
|
"s",
|
|
|
|
unique ? unique : name);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(reply, "u", &u);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
c->euid = u;
|
|
|
|
c->mask |= SD_BUS_CREDS_EUID;
|
|
|
|
|
|
|
|
reply = sd_bus_message_unref(reply);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (need_selinux) {
|
|
|
|
const void *p = NULL;
|
|
|
|
size_t sz = 0;
|
|
|
|
|
|
|
|
r = sd_bus_call_method(
|
|
|
|
bus,
|
|
|
|
"org.freedesktop.DBus",
|
|
|
|
"/org/freedesktop/DBus",
|
|
|
|
"org.freedesktop.DBus",
|
|
|
|
"GetConnectionSELinuxSecurityContext",
|
|
|
|
&error,
|
|
|
|
&reply,
|
|
|
|
"s",
|
|
|
|
unique ? unique : name);
|
|
|
|
if (r < 0) {
|
|
|
|
if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
|
|
|
|
return r;
|
|
|
|
|
|
|
|
/* no data is fine */
|
|
|
|
} else {
|
|
|
|
r = sd_bus_message_read_array(reply, 'y', &p, &sz);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
c->label = strndup(p, sz);
|
|
|
|
if (!c->label)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
|
|
|
|
}
|
2014-11-24 22:11:53 +01:00
|
|
|
}
|
2013-11-30 04:14:10 +01:00
|
|
|
}
|
2013-12-03 18:01:26 +01:00
|
|
|
|
|
|
|
r = bus_creds_add_more(c, mask, pid, 0);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-11-30 04:14:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (creds) {
|
|
|
|
*creds = c;
|
|
|
|
c = NULL;
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:01:26 +01:00
|
|
|
return 0;
|
2013-11-30 04:14:10 +01:00
|
|
|
}
|
|
|
|
|
2017-12-18 14:48:16 +01:00
|
|
|
_public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
|
|
|
|
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
|
|
|
|
bool do_label, do_groups;
|
|
|
|
pid_t pid = 0;
|
|
|
|
int r;
|
2013-11-30 04:14:10 +01:00
|
|
|
|
|
|
|
assert_return(bus, -EINVAL);
|
2015-03-13 14:08:00 +01:00
|
|
|
assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
|
2017-12-18 14:48:16 +01:00
|
|
|
assert_return(ret, -EINVAL);
|
2013-11-30 04:14:10 +01:00
|
|
|
assert_return(!bus_pid_changed(bus), -ECHILD);
|
2017-06-26 18:24:58 +02:00
|
|
|
|
2014-03-19 21:41:21 +01:00
|
|
|
if (!BUS_IS_OPEN(bus->state))
|
|
|
|
return -ENOTCONN;
|
|
|
|
|
2017-12-18 14:48:16 +01:00
|
|
|
if (!bus->is_local)
|
|
|
|
mask &= ~SD_BUS_CREDS_AUGMENT;
|
2015-11-11 12:55:32 +01:00
|
|
|
|
|
|
|
do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
|
2017-12-30 15:19:15 +01:00
|
|
|
do_groups = bus->n_groups != (size_t) -1 && (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS);
|
2014-10-22 19:43:09 +02:00
|
|
|
|
2015-06-07 03:24:45 +02:00
|
|
|
/* Avoid allocating anything if we have no chance of returning useful data */
|
2017-12-30 15:19:15 +01:00
|
|
|
if (!bus->ucred_valid && !do_label && !do_groups)
|
2014-10-22 19:43:09 +02:00
|
|
|
return -ENODATA;
|
|
|
|
|
|
|
|
c = bus_creds_new();
|
|
|
|
if (!c)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
if (bus->ucred_valid) {
|
2017-12-30 15:15:03 +01:00
|
|
|
if (pid_is_valid(bus->ucred.pid)) {
|
2014-11-28 15:58:03 +01:00
|
|
|
pid = c->pid = bus->ucred.pid;
|
|
|
|
c->mask |= SD_BUS_CREDS_PID & mask;
|
|
|
|
}
|
2014-10-22 19:43:09 +02:00
|
|
|
|
2017-12-30 15:15:03 +01:00
|
|
|
if (uid_is_valid(bus->ucred.uid)) {
|
bus: use EUID over UID and fix unix-creds
Whenever a process performs an action on an object, the kernel uses the
EUID of the process to do permission checks and to apply on any newly
created objects. The UID of a process is only used if someone *ELSE* acts
on the process. That is, the UID of a process defines who owns the
process, the EUID defines what privileges are used by this process when
performing an action.
Process limits, on the other hand, are always applied to the real UID, not
the effective UID. This is, because a process has a user object linked,
which always corresponds to its UID. A process never has a user object
linked for its EUID. Thus, accounting (and limits) is always done on the
real UID.
This commit fixes all sd-bus users to use the EUID when performing
privilege checks and alike. Furthermore, it fixes unix-creds to be parsed
as EUID, not UID (as the kernel always takes the EUID on UDS). Anyone
using UID (eg., to do user-accounting) has to fall back to the EUID as UDS
does not transmit the UID.
2015-01-18 13:55:55 +01:00
|
|
|
c->euid = bus->ucred.uid;
|
|
|
|
c->mask |= SD_BUS_CREDS_EUID & mask;
|
2014-11-28 15:58:03 +01:00
|
|
|
}
|
|
|
|
|
2017-12-30 15:15:03 +01:00
|
|
|
if (gid_is_valid(bus->ucred.gid)) {
|
bus: use EUID over UID and fix unix-creds
Whenever a process performs an action on an object, the kernel uses the
EUID of the process to do permission checks and to apply on any newly
created objects. The UID of a process is only used if someone *ELSE* acts
on the process. That is, the UID of a process defines who owns the
process, the EUID defines what privileges are used by this process when
performing an action.
Process limits, on the other hand, are always applied to the real UID, not
the effective UID. This is, because a process has a user object linked,
which always corresponds to its UID. A process never has a user object
linked for its EUID. Thus, accounting (and limits) is always done on the
real UID.
This commit fixes all sd-bus users to use the EUID when performing
privilege checks and alike. Furthermore, it fixes unix-creds to be parsed
as EUID, not UID (as the kernel always takes the EUID on UDS). Anyone
using UID (eg., to do user-accounting) has to fall back to the EUID as UDS
does not transmit the UID.
2015-01-18 13:55:55 +01:00
|
|
|
c->egid = bus->ucred.gid;
|
|
|
|
c->mask |= SD_BUS_CREDS_EGID & mask;
|
2014-11-28 15:58:03 +01:00
|
|
|
}
|
2014-10-22 19:43:09 +02:00
|
|
|
}
|
|
|
|
|
2015-06-07 03:24:45 +02:00
|
|
|
if (do_label) {
|
2014-10-22 19:43:09 +02:00
|
|
|
c->label = strdup(bus->label);
|
2014-10-22 22:06:53 +02:00
|
|
|
if (!c->label)
|
2014-10-22 19:43:09 +02:00
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
|
|
|
|
}
|
|
|
|
|
2017-12-30 15:19:15 +01:00
|
|
|
if (do_groups) {
|
|
|
|
c->supplementary_gids = newdup(gid_t, bus->groups, bus->n_groups);
|
|
|
|
if (!c->supplementary_gids)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
c->n_supplementary_gids = bus->n_groups;
|
|
|
|
|
|
|
|
c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
|
|
|
|
}
|
|
|
|
|
sd-bus: update to current kernel version, by splitting off the extended KDBUS_ITEM_PIDS structure from KDBUS_ITEM_CREDS
Also:
- adds support for euid, suid, fsuid, egid, sgid, fsgid fields.
- makes augmentation of creds with data from /proc explicitly
controllable to give apps better control over this, given that this is
racy.
- enables augmentation for kdbus connections (previously we only did it
for dbus1). This is useful since with recent kdbus versions it is
possible for clients to control the metadata they want to send.
- changes sd_bus_query_sender_privilege() to take the euid of the client
into consideration, if known
- when we don't have permissions to read augmentation data from /proc,
don't fail, just don't add the data in
2014-11-24 21:41:40 +01:00
|
|
|
r = bus_creds_add_more(c, mask, pid, 0);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2014-10-22 19:43:09 +02:00
|
|
|
*ret = c;
|
2014-10-22 22:06:53 +02:00
|
|
|
c = NULL;
|
2014-10-22 19:43:09 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-12-18 14:48:16 +01:00
|
|
|
#define append_eavesdrop(bus, m) \
|
2017-12-18 14:21:34 +01:00
|
|
|
((bus)->is_monitor \
|
2015-02-03 02:05:59 +01:00
|
|
|
? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
|
2014-03-19 04:17:00 +01:00
|
|
|
: (m))
|
|
|
|
|
2017-12-18 14:48:16 +01:00
|
|
|
int bus_add_match_internal(
|
2013-12-03 18:01:26 +01:00
|
|
|
sd_bus *bus,
|
2017-12-18 20:34:21 +01:00
|
|
|
const char *match) {
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-03-19 04:17:00 +01:00
|
|
|
const char *e;
|
|
|
|
|
2013-12-03 18:01:26 +01:00
|
|
|
assert(bus);
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2017-12-18 14:48:16 +01:00
|
|
|
if (!bus->bus_client)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
e = append_eavesdrop(bus, match);
|
2014-03-19 04:17:00 +01:00
|
|
|
|
2013-12-03 18:01:26 +01:00
|
|
|
return sd_bus_call_method(
|
|
|
|
bus,
|
|
|
|
"org.freedesktop.DBus",
|
2013-12-23 03:30:41 +01:00
|
|
|
"/org/freedesktop/DBus",
|
2013-12-03 18:01:26 +01:00
|
|
|
"org.freedesktop.DBus",
|
|
|
|
"AddMatch",
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"s",
|
2014-03-19 04:17:00 +01:00
|
|
|
e);
|
2013-03-19 20:03:16 +01:00
|
|
|
}
|
|
|
|
|
2017-12-18 14:48:16 +01:00
|
|
|
int bus_remove_match_internal(
|
2013-12-03 18:01:26 +01:00
|
|
|
sd_bus *bus,
|
|
|
|
const char *match) {
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-03-19 04:17:00 +01:00
|
|
|
const char *e;
|
|
|
|
|
2013-12-03 18:01:26 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(match);
|
|
|
|
|
2017-12-18 14:48:16 +01:00
|
|
|
if (!bus->bus_client)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
e = append_eavesdrop(bus, match);
|
2014-03-19 04:17:00 +01:00
|
|
|
|
2017-12-18 20:50:26 +01:00
|
|
|
/* Fire and forget */
|
|
|
|
|
|
|
|
return sd_bus_call_method_async(
|
2013-12-03 18:01:26 +01:00
|
|
|
bus,
|
2017-12-18 20:50:26 +01:00
|
|
|
NULL,
|
2013-12-03 18:01:26 +01:00
|
|
|
"org.freedesktop.DBus",
|
2013-12-23 03:30:41 +01:00
|
|
|
"/org/freedesktop/DBus",
|
2013-12-03 18:01:26 +01:00
|
|
|
"org.freedesktop.DBus",
|
|
|
|
"RemoveMatch",
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"s",
|
2014-03-19 04:17:00 +01:00
|
|
|
e);
|
2013-12-03 18:01:26 +01:00
|
|
|
}
|
|
|
|
|
2014-10-22 19:17:24 +02:00
|
|
|
_public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
|
2013-04-23 16:18:17 +02:00
|
|
|
const char *mid;
|
|
|
|
int r;
|
|
|
|
|
2013-11-11 23:44:00 +01:00
|
|
|
assert_return(bus, -EINVAL);
|
|
|
|
assert_return(name, -EINVAL);
|
|
|
|
assert_return(machine, -EINVAL);
|
|
|
|
assert_return(!bus_pid_changed(bus), -ECHILD);
|
2013-12-18 02:23:07 +01:00
|
|
|
assert_return(service_name_is_valid(name), -EINVAL);
|
2013-04-23 16:18:17 +02:00
|
|
|
|
2015-04-23 16:23:15 +02:00
|
|
|
if (!bus->bus_client)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2014-03-19 21:41:21 +01:00
|
|
|
if (!BUS_IS_OPEN(bus->state))
|
|
|
|
return -ENOTCONN;
|
|
|
|
|
2013-04-23 16:18:17 +02:00
|
|
|
if (streq_ptr(name, bus->unique_name))
|
|
|
|
return sd_id128_get_machine(machine);
|
|
|
|
|
2013-11-11 23:44:00 +01:00
|
|
|
r = sd_bus_message_new_method_call(
|
|
|
|
bus,
|
2014-02-19 23:54:58 +01:00
|
|
|
&m,
|
2013-11-11 23:44:00 +01:00
|
|
|
name,
|
|
|
|
"/",
|
|
|
|
"org.freedesktop.DBus.Peer",
|
2014-02-19 23:54:58 +01:00
|
|
|
"GetMachineId");
|
2013-11-11 23:44:00 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2014-01-22 20:45:05 +01:00
|
|
|
r = sd_bus_message_set_auto_start(m, false);
|
2013-11-11 23:44:00 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-04-23 16:18:17 +02:00
|
|
|
|
2013-11-11 23:44:00 +01:00
|
|
|
r = sd_bus_call(bus, m, 0, NULL, &reply);
|
2013-04-23 16:18:17 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(reply, "s", &mid);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
return sd_id128_from_string(mid, machine);
|
|
|
|
}
|